JavaScript非同期の実装

3594 ワード

キーワード:非同期
Javascript言語の実行環境は「単一スレッド」(single thread)です.
「単一スレッド」とは、一度に1つのタスクしか完了できないことを意味します.複数のタスクがある場合は、キューに並ばなければなりません.前のタスクが完了し、後のタスクが実行されます.このように、jQueryのキューはこの特性に基づいて実現されます.このパターンの長所と短所を見てみましょう.
  • の利点:実現は比較的簡単で、実行環境は比較的単純である.
  • の欠点:1つのタスクに時間がかかると、プログラム全体の実行が遅延します.一般的なブラウザの応答なし(偽)
  • この問題を解決するために、Javascript言語は、タスクの実行モードを同期(Synchronous)と非同期(Asynchronous)の2つに分けます.
  • 「同期モード」は前段のモードであり、後のタスクは前のタスクが終了するのを待ってから実行され、プログラムの実行順序はタスクの並び順と一致し、同期される.
  • 「非同期モード」は全く異なり、各タスクには1つ以上のコールバック関数(callback)があり、前のタスクが終了した後、後のタスクを実行するのではなく、コールバック関数を実行し、後のタスクは前のタスクの終了を待たずに実行され、プログラムの実行順序はタスクの並び順と一致せず、非同期である.

  • 以下は「非同期モード」の4つの方法で、構造が合理的で、性能が優れ、メンテナンスが容易なJavascriptプログラムを書くことができることを理解しています.
    一、コールバック関数
    これは非同期プログラミングの最も基本的な方法です.2つの関数f 1およびf 2があると仮定し、後者は前者の実行結果を待つ.
      f1();
      f2();
    

    f 1が時間のかかるタスクである場合、f 1を書き換え、f 2をf 1のコールバック関数に書くことを考慮することができる.
      function f1(callback){
        setTimeout(function () {
          // f1     
          callback();
        }, 1000);
      }
    

    実行コードは、*f 1(f 2);
    この方式を採用して、私達は同期操作を非同期操作に変えて、f 1はプログラムの運行を塞ぐことがなくて、先にプログラムの主要な論理を実行することに相当して、時間のかかる操作を実行を延期します.コールバック関数の利点は、単純で理解しやすく、導入しやすいことです.欠点は、コードの読み取りとメンテナンスに不利であり、各部分間が高度に結合され、プロセスが混乱し、各タスクに1つのコールバック関数しか指定できないことです.
    二、事件の傍受
    もう1つの考え方は、イベント駆動モードを採用することです.タスクの実行は、イベントが発生するかどうかによって、コードの順序に依存しません.
    やはりf 1とf 2を例に挙げます.まず、f 1にイベント(ここではjQueryの表記)をバインドする.
      f1.on('done', f2);
    

    上記の行のコードは、f 1にdoneイベントが発生するとf 2が実行されることを意味する.次に、f 1を書き換える:
      function f1(){
        setTimeout(function () {
          // f1     
          **f1.trigger('done');**
        }, 1000);
      }
    

    f1.trigger('done')は、実行が完了すると、直ちにdoneイベントがトリガーされ、f 2の実行が開始されることを示す.
    この方法の利点は,複数のイベントをバインドでき,各イベントに複数のコールバック関数を指定でき,「デカップリング」が可能であることであり,モジュール化を実現するのに有利であるという欠点は,プログラム全体がイベント駆動型になり,実行プロセスが不明確になることである.
    三、発行/購読
    前節の「イベント」は、完全に「信号」と理解できます.
    タスクの実行が完了すると、信号センターに信号が「パブリッシュ」(publish)され、他のタスクは信号センターに信号を「サブスクリプション」(subscribe)することができ、いつ自分が実行を開始できるかを知る「信号センター」があると仮定します.これを「パブリッシュ/サブスクリプションモード」publish-subscribe patternといい、「オブザーバーモード」とも呼ばれるこのモードは様々な実装があり、以下にBen AlmanのTiny Pub/subを採用し、これはjQueryのプラグインである.まず、f 2は「信号センター」jQueryに「done」信号を購読する.*jQuery.subscribe("done", f2);
    そして、f 1は、以下のように書き換えられる.
      function f1(){
        setTimeout(function () {
          // f1     
          **jQuery.publish("done");**
        }, 1000);
      }
    

    jQuery.publish(「done」)は、f 1の実行が完了すると、「信号中心」jQueryに「done」信号が発行され、f 2の実行が開始されることを意味する.また、f 2の実行が完了すると、unsubscribe(unsubscribe)の購読をキャンセルすることもできます.*jQuery.unsubscribe("done", f2);
    この方法の性質は「イベントリスニング」と類似しているが,後者より明らかに優れている.メッセージセンターを表示することで、どのくらいの信号が存在するか、各信号にどのくらいのサブスクライバが存在するかを知ることができ、プログラムの実行を監視することができます.
    四、Promisesオブジェクト
    PromisesオブジェクトはCommonJSワークグループが提案した仕様で、非同期プログラミングに統一インタフェースを提供することを目的としています.
    簡単に言えば、各非同期タスクは、コールバック関数を指定できるthenメソッドを持つPromiseオブジェクトを返すことを考えています.例えば、f 1のコールバック関数f 2は、*f 1()と書くことができる.then(f2);
      function f1(){
        var dfd = $.Deferred();
        setTimeout(function () {
          // f1     
          dfd.resolve();
        }, 500);
        **return dfd.promise;**
      }
    

    このように書く利点は、コールバック関数がチェーン式の書き方になり、プログラムの流れがはっきり見えることができ、一連の組み合わせ方法があり、多くの強力な機能を実現することができることです.例えば、複数のコールバック関数:*f 1()を指定する.then(f2).then(f3);
    例えば、エラー発生時のコールバック関数:*f 1()を指定する.then(f2).fail(f3);
    また、タスクが完了した場合にコールバック関数を追加すると、コールバック関数がすぐに実行されるという3つの方法にはメリットがありません.だから、ある事件や信号を逃したかどうか心配する必要はありません.この方法の欠点は,作成と理解が相対的に難しいことである.
    [参考文献][参考文献]:http://www.ruanyifeng.com/blog/2012/12/asynchronous%EF%BC%BFjavascript.html