Javascript非同期プログラミング方法のまとめ

7055 ワード

  • コールバック関数は、2つの関数f 1とf 2があると仮定し、後者は前者の実行結果を待つ.f 1()f 2()f 1が時間がかかるタスクであれば、f 1に書き換え、f 2をf 1のコールバック関数と書くことが考えられます.
    function f1(callback){
       setTimeout(function(){
            //f1  
            callback();
        },1000);
    }
    
    実行するとf 1(f 2)になる.この方法を採用して同期を非同期にしても、f 1はプログラムの実行を滞らせず、プログラムを先に実行する主要なロジックに相当し、時間の経過を全部部分的に遅らせて実行します.コールバック関数の利点:簡単で、分かりやすく、展開ができます.短所:コードの読み取りとメンテナンスに不利です.一つの同期(ブロッキング)では、コールバックの例を用いて、Fnc 1コードの実行が完了した後にFnc 2コードを実行することを目的とする.
    var func1 = function(callback){
           // do something 
          (callback && typeof(callback) === "function") && callback();
    }
    func1(func2);
    var func2 = function(){}
    
  • より多くのコールバック関数を参照してください.
  • JavaScriptコールバック関数
  • JAvascriptコールバック関数
  • JavaScript:返事は何の鬼ですか?
  • JSコールバック関数詳細
  • イベント傍受タスクの実行は、コードの順序によらず、あるイベントが発生するかどうかによって決まる.f 1バインドされたイベント:f1.on('done', f2);f 1でdoneイベントが発生すると、f 2が実行される.そして、f 1を書き換える
    function f1(){
    setTimeout(function*(){
         // f1     
         f1.trigger('done');
        },1000);
    }
    
    利点:分かりやすく、複数のイベントを結びつけることで、各イベントごとに複数のコールバック関数を指定して結合し、モジュール化することができる.
  • 配信/購読例:jqueryの中の一つのプラグイン:Tinpub/Sub
  • f 2信号センター「jquery購読」done信号:jquery.subscribe(「done」、f 2)
  • f 1関数は以下の通りである.
    function f1(){
        setTimeout(function(){
              // f1     
               jquey.publish('done');
        }, 1000);
     }
    
    jquey.publish('done')つまり、f 1の実行が完了したら、信号センターにdone信号を送信し、f 2の実行を開始する.f 2実行後、購読をキャンセルすることもできます.jquery.unsubscribe("done", f2);
  • Promisesオブジェクト:非同期プログラムのための統一インターフェースを提供します.思想:各非同期タスクはPromiseオブジェクトに戻り、オブジェクトにはthenメソッドがあり、コールバック関数を許可します.Promiseの3つの状態:
  • Pending:Promiseオブジェクト例作成時の初期状態.
  • Fulfilled:成功した状態
  • Rejectied:失敗した状態Promise-->reolved->then(コールバック)または->reject-->catch.Promiseは待ち状態から他の状態になると、いつまでも状態を変えることができなくなります.
     const instance = new Promise((resolve, reject) => {
       //       
       if(/*      */) {
           resolve(value);
       } else {
           reject(error);
           }
       }
     })
     instance.then(value => {
         // do something...
      }, error => {
           // do something...
      })
    
    コンストラクション内部のコードは直ちに実行されます.then方法は新しいPromiseの例を返します.二つの場合に分けて見られます.
  • 戻り値指定は新たなPromiseオブジェクトであり、return new Promise(…)のような場合は何も言えませんが、帰ってきたのはPromiseですので、後からthenメソッドを呼び続けてもいいです.
  • 戻り値はPromiseではありません.例えば、return 1はPromiseに戻り、このPromiseはすぐにレシオを実行します.したがって、まだチェーン式でthenメソッドを呼び出すことができます.(注:return文が指定されていない場合は、undefinedに戻ります).
  • 一例
  • function sayHi(name) {
       return new Promise((resolve, reject) => {
             setTimeout(() => {
                 resolve(name);
              }, 2000)
        })
    }
    sayHi('  ')
       .then(name => {
             console.log(`  , ${name}`);
             return sayHi('  ');    //    resolved                 then
          })
         // name     then       
       .then(name => {                
           console.log(`  , ${name}`);
           return sayHi('    ');
         })
       .then(name => {
           console.log(`  , ${name}`);
       })
     //   ,   
     //   ,   
     //   ,     
    
  • 例二
  •  read('./file-01.txt', 'utf8')
        .then(data => {
          //    read         promise ,  read          promise
          //      promise                then   resolve 
              return read(data, 'utf8');
          }, err => {
              console.log(err);
        })
        .then(data => {
          //            ,              then       
            return [data];
         }, err => {
           console.log(err);
         })
        .then(data => {
          //          
           console.log(data);
           //     return ,        undefined ,   then       undefined
            }, err => {
            console.log(err);
          })
        .then(data => {
        //     then      ,     undefined
        // undefined     
          console.log(data);
          //     ,       then   reject 
            throw new Error('xxx');
        }, err => {
            console.log(err);
      })
       .then(null, err => {
          //       then     ,    reject    
          // reject          then     undefined 
        console.log(err);
      })
      .then(data => {
          //     then         ,    undefined 
          console.log('resolve');        
        }, err => {
          console.log('reject');
      });
    
  • 例3:errの代わりにcatchを使う
  •  read('./file-01.txt', 'utf8')
        .then(data => {
            return read(data, 'utf8');
        })
      .then(data => {
          return [data];
      })
      .then(data => {
          console.log(data);
      })
      .then(data => {
        console.log(data);
          //      ,           
          //       then     reject   ,       catch
          throw new Error('xxx');
        })
      .then(null)
      .then(data => {
          console.log('resolve');        
        })
      .catch(err => {
          console.log(err);
      });
    
  • async/await
  • async/awaitはPromiseに基づいて実現され、通常のコールバック関数には使用できません.
  • Promiseと同じ、渋滞していない.
  • 同期コードのように見えます.
  • 一つの関数にasyncを加えると、その関数はPromiseに戻ります.(指定された戻り値がPromiseオブジェクトではなく、一つのPromiseにも戻りますが、直ちにreresoveで、処理方式はthenメソッドと同じですので、async関数はreturnで戻ります.thenメソッドにおけるコールバック関数のパラメータとなります.単独のasync関数は、Promiseが実行する機能と同じです.
  • awaitは非同期で待っています.Promiseであるため、awaitの後ろにPromiseオブジェクトを書くべきです.Promiseの対象でないと、即座にresoveのPromise
  • 一例
      let fs = require('fs')
      function read(file) {
      return new Promise(function(resolve, reject) {
          fs.readFile(file, 'utf8', function(err, data) {
          if (err) reject(err)
          resolve(data)
          })
      })
      }
      async function readResult(params) {
      try {
          let p1 = await read(params, 'utf8')
          //await       Promise  ,
          //await       return   ,       then  。
          let p2 = await read(p1, 'utf8')
          let p3 = await read(p2, 'utf8')
          console.log('p1', p1)
          console.log('p2', p2)
          console.log('p3', p3)
          return p3
      } catch (error) {
          console.log(error)
      }
      }
      readResult('1.txt').then( // async        promise
      data => {
          console.log(data)
      },
      err => console.log(err)
      )
      // p1 2.txt
      // p2 3.txt
      // p3   
      //   
    
  • 例二
  • function readAll() {
       read1()
       read2()//        
      }
    async function read1() {
       let r = await read('1.txt','utf8')
       console.log(r)
     }
    async function read2() {
       let r = await read('2.txt','utf8')
       console.log(r)
     }
    readAll() // 2.txt 3.txt
    
  • 例三
  • async function func() {
        try {
            const num1 = await 200;
            console.log(`num1 is ${num1}`);
            const num2 = await Promise.reject('num2 is wrong!');
            console.log(`num2 is ${num2}`);
            const num3 = await num2 + 100;
            console.log(`num3 is ${num3}`);
        } catch (error) {
            console.log(error);
        }
     }
    
    func();
    // num1 is 200
    //    
    // num2 is wrong!
    
    参考:-Javascript非同期プログラミングの4つの方法-非同期方法の開発プロセス-JS非同期プログラミングの6つの方法