ES 6 PromiseとAsync/awaitの使用

10071 ワード

Javascript言語の実行環境は「シングルスレッド」であることを知っているかもしれません.
「シングルスレッド」とは、一回に一つしかできないミッションのことです.複数のタスクがある場合は、前のタスクを完了し、後のタスクを実行しなければなりません.これを類推します.
このようなモードのメリットは実現が比較的簡単で、実行環境が比較的単純であることです.悪いところは一つのタスクがある限り、時間がかかります.後のタスクは並んで待つ必要があります.プログラム全体の実行を遅らせます.よくあるブラウザは無応答(仮死)で、あるJavascriptコードが長時間運行されているため、ページカード全体がこの場所にあるため、他のタスクは実行できません.
この問題を解決するために、Javascript言語はタスクの実行モードを二つに分けます.同期(Synchronous)と非同期(Aynchronous).
1.コールバック
コールバックは非同期プログラミングの最も基本的な方法である.
2つの関数f 1とf 2があると仮定し、前者の実行結果を待つ.
f1();
f2();
f 1が時間がかかるタスクであれば、f 1を書き換え、f 2をf 1のコールバック関数として書くことが考えられます.
function f1(callback){
  setTimeout(function () {
    // f1     
    callback();
  }, 1000);
}
実行コードは以下のようになります.
f1(f2);
このようにして、同期動作を非同期操作に変えました.f 1はプログラムの実行を滞らせません.先にプログラムを実行する主要なロジックに相当します.時間がかかる操作を実行を遅らせます.コールバック関数の利点は、単純で分かりやすく配置されており、欠点はコードの読み取りと維持に不利であり、各部分の間で高度に結合され、流れが混乱し、各タスクは一つのコールバック関数しか指定できない.
2.PromisePromisesオブジェクトは、非同期プログラミングのための統一インターフェースを提供するためにCommonJS作業グループによって提案された仕様である.
簡単に言えば、各非同期タスクはPromiseオブジェクトに戻り、オブジェクトにはthenメソッドがあり、コールバック関数の指定が可能です.Promisesの出現は非同期化のジレンマを大幅に改善し、逆転地獄を回避し、ネスト層が改善された.
基本アプリ
  • Promise.resove()
  • Promise.reject()
  • Promise.prototype.then()
  • Promise.prototype.ctch()
  • Promise.all()/すべての完了
  • Promise.race()/競速は、一つで
  • です.
    具体的なapiの紹介は阮一峰大神のECMAScript 6入門を見てください.ここで簡単なシーンをいくつか挙げて実現します.
    二つの非同期要求をシミュレートする.
    コードの概要を説明するために、promiseのrejected状態に関するreject()とcatch()の方法は省略されます.
      // 1  
      function getData1 () {
        return new Promise(function (resolve, reject) {
          setTimeout(() => {
            console.log('1   ')
            resolve('       1111 ')
          }, 2000)
        })
      }
      // 2  
      function getData2 (params) {
        return new Promise(function (resolve, reject) {
          setTimeout(() => {
            console.log('2   ')
            resolve('       22222 !params:' + params)
          }, 1500)
        })
      }
    
    promiseが非同期を実現し、異ステップに整列する.
    1要求が完了したら、1の応答パラメータを2に入力し、2の要求を送信します.
      function promiseDemo () {
        getData1()
          .then(res => {
            return getData2(res)
          })
          .then(res => {
            console.log(res)
          })
      }
      promiseDemo()
      // 1   
      // 2   
      //        22222 !params:       1111       3500 ms
    
    promise.allは、非同期の折り返しを実現し、すべての完成を同時にする.
    1要求、2要求を同時に送信し、両方の応答を受信して実行する.
      function promiseDemo () {
        Promise.all([getData1(), getData2()]).then(function (res) {
          console.log(res)
        })
      }
      // 2   
      // 1   
      // ["       1111 ", "       22222 !params:undefined"]      2000 ms
    
    promise.race()非同期フィードバックを実現し、併発競争速度を競います.
    1要求、2要求を同時に送信し、そのうちの一つは要求を受取ったら実行する.
      function promiseDemo () {
        Promise.race([getData1(), getData2()]).then(function (res) {
          console.log(res)
        })
      }
      // 2   
      //        22222 !params:undefined       1500 ms
      // 1      
    
    これによってPromiseオブジェクトは非常に有用であり、非同期のプロセスに対する制御が大幅に改善され、.then()の方法によってチェーンコールが可能である.しかし、.then() .catch()の使用はコードが非常に醜く、入れ子も深いため、async/awaitが出てきます.
    Async/await
    Async/awaitはJavascriptが非同期プログラムを作成する新しい方法です.従来の非同期法は,コールバック関数とPromiseの両方にほかならなかった.しかしAsync/awaitはPromiseの上に成り立っています.
    どのようにAync関数を使いますか?
    私達はやはり阮一峰大神のECMAScript 6入門の例を見に来ました.
    async function timeout(ms) {
      await new Promise((resolve) => {
        setTimeout(resolve, ms);
      });
    }
    
    async function asyncPrint(value, ms) {
      await timeout(ms);
      console.log(value);
    }
    
    asyncPrint('hello world', 50);
    
    上のコードで50ミリ秒を指定したら、ハローワールドを出力します.さらに、async関数は完全に複数の非同期動作と見なされ、Promiseオブジェクトとして包装されています.awaitコマンドは内部thenコマンドのシンタックスキャンディーです.
    具体的な例を見ます.
    asyncは非同期の折り返しを実現して列に並ぶ.
    1要求が完了したら、1の応答パラメータを2に入力し、2の要求を送信します.
    上記のpromiseの実現方法はthenのチェーンを通じて呼び出されましたが、asyncを採用するともっと簡潔で明瞭です.
      async function asyncDemo () {
        const r1 = await getData1()
        const r2 = await getData2(r1)
        console.log(r2)
      }
      // 1   
      // 2   
      //        22222 !params:       1111       3500 ms
    
    同期した表記で非同期コードを実現しました.get Data 1を待つ非同期関数が実行された後、戻り値がr 1に割り当てられ、r 2に着信し、実行r 2にある.
    asyncは非同期で合併する.
    1要求、2要求を同時に発送し、到着を要求する順序を定める.
    もしこのような業務需要があるなら、二つの要求を同時にしますが、要求を受ける順番はどうすればいいですか?ここはまだ阮一峰大神のコードを参考にしています.
      async function asyncDemo2 () {
        const arr = [getData1, getData2]
        const textPromises = arr.map(async function (doc) {
          const response = await doc()
          return response
        })
        //      
        for (const textPromise of textPromises) {
          console.log(await textPromise);
        }
      }
      // 2               (  2  1500ms   )   2   
      // 1   
      //        1   (for .. of )        
      //        22222 !params:undefined
    
    面コードでは、mapメソッドのパラメータはasync関数であるが、ASync関数の内部のみが転送され、外部は影響を受けないため、同時に実行されている.後のfor.of循環内部はawaitを使用していますので、順番に出力することができます.
    どのようにBTの需要はすべて実現することができます.
    asyncまとめ
    彼は非同期コードを明らかにしなくなったのも欠点です.でも、実際の状況によって最適な非同期プログラムを選ぶのが一番いいです.asyncはGenerator関数のシンタックス飴です.だから、内部原理をもっと深く理解したいです.早くGenerator関数を見に行きます.