JavaScriptのasync/await実行手順詳細

22907 ワード

async/await実行手順詳細
JavaScriptの中のasync/awaitはAync Functionの特性の中のキーワードで、字面の意味から理解します:asyncは“非歩”の略字で、awaitはasync waitの略字だと見なすことができます.だからasynctionは非同期であるということをよく理解しておくべきです.awaitは非同期的な方法の完成を待つために使われます.
まず簡単にasync/awaitを紹介します.
  • async/awaitは、非同期コードを作成する新しい方法です.前の非同期コードの案はリプライとプロミスです.
  • async/awaitはpromiseに基づいている
  • async/awaitはpromiseのようにブロックされていません.
  • async/awaitは、非同期コードを見て、より同期コードのように表現する.
  • もう一つ面白い文法の規定があります.awaitはasync関数にしか現れません.そして、注意深い友達から質問があります.awaitがasync関数の中にしか現れないなら、このasync関数はどうやって呼びますか?
    1.asyncはどうやって返しますか?
    async function testAsync() {
        return "hello async";
    }
    const result = testAsync();
    console.log(result);
    
        : Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: "hello async"}
    
    async関数はPromiseオブジェクトを返します.もし関数の中でreturnの直接量があれば、asyncはこの直接量をPromise.resolive()を通じてPromiseオブジェクトにカプセル化します.
    戻り値がない場合:
    async function testAsync1() {
        console.log("hello async");
    }
    let result1 = testAsync1();
    console.log(result1);
    
        : Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: undefined}
    
    結果はPromise.resoveに戻ります.
    ですから、awaitがない場合は、async関数を実行します.すぐに実行して、Promiseオブジェクトに戻ります.そして、後の文をブロックしません.これは普通にPromiseオブジェクトに戻る関数と同じです.
    次のポイントはawaitキーワードにあります.
    2.await待ちの仕組み
    一般に、awaitはasync関数の完成を待っていると考えられています.正確には、awaitが待っているのは表現です.この表現はPromiseオブジェクトまたは他の値です.
    async関数はPromiseオブジェクトに戻るので、awaitはasync関数の戻り値を待つために使えます.これはawaitがasync関数を待っていると言ってもいいですが、それなどは実際には戻り値です.awaitの後は実際に普通関数の呼び出しや直接量に接続できます.
    awaitは待ちたいもの、Promiseの対象、または他の値を待っています.awaitは演算子で、表現を構成するために用いられます.await表現の演算結果は、それなどに依存します.
    もしそれがPromiseオブジェクトでないなら、await表式の演算結果はそれが待っているものです.
    もしそれがPromiseオブジェクトであるなら、awaitは忙しいです.後のコードをブロックし、Promiseオブジェクトresoveを待って、resoveの値を得て、await表現の演算結果とします.これはawaitがasync関数に使わなければならない理由です.async関数の呼び出しは、ブロックを引き起こすことはありません.その内部のすべてのブロックは、Promiseオブジェクトに非同期的に実装されます.簡単な例を見てください.
    function testSome () {
        console.log("  testSome ");
        return "testSome ";
    }
    
    async function testAsync() {
        console.log("  testAsync");
        return Promise.resolve("hello async");
    }
    
    async function test() {
        console.log("test start...");
        const v1 = await testSometing();  //   1
        console.log(v1);
        const v2 = await testAsync();
        console.log(v2);
    }
    
    test();
    var promise = new Promise((resolve)=> {
    	 console.log("promise start..");
    	 resolve("promise");   //   2
    });	
    promise.then((val)=> console.log(val));
    
    console.log("test end...")
    
    出力結果:
    
     test start...
       testSome 
     promise start..
     test end...
     testSome 
       testAsync
     promise
     hello async
    
    
    実行順序
  • 1.test関数が実行されるとき
  •   const v1 = await testSometing()
    testSomeという関数を先に実行し、「testSomeを実行する」という文字列を印刷します.
  • 2.そしてawaitがスレッドを譲るので、後ろの
  • var promise = new Promise((resolve)=> {
    	 console.log("promise start..");
    	 resolve("promise");   //   2
    });	
    
    そして「promise start...」をプリントアウトします.これから帰ってくるこのpromiseをpromiseの列に入れます.
  • 3.引き続き印刷
  •   test  end...
  • 4.本ラウンドのイベントサイクルが終了すると、async関数(test関数)に戻ってきます.これまでawaitの後の表式の戻り値を待っています.testSomeはasync関数ではないので、文字列
  •   testSome
    
  • 5.test関数は引き続き実行し、const v 2=await testAync()に実行し、前と同じように出力
  •    testAsync
    
  • 6.そしてtest関数を飛び出して、後続コードを実行するとイベントサイクルがpromiseのキューに入り、promise.thenの中の文を実行し、プリント
  •  promise
    
  • 7.その後、再びtest関数に戻って実行します.
  •  hello async
    
    これはasync/await関数の後のjsの実行順です.
    3.async/await優勢
    一例をあげて、then()チェーンとasync/awaiを比較します.
    3つのステップを実行すると、各ステップは前のステップの結果を必要とします.
    function step1(n) {
        console.log(`step1 with ${n}`);
        return takeLongTime(n);
    }
    
    function step2(m, n) {
        console.log(`step2 with ${m} and ${n}`);
        return takeLongTime(m + n);
    }
    
    function step3(k, m, n) {
        console.log(`step3 with ${k}, ${m} and ${n}`);
        return takeLongTime(k + m + n);
    }
    
    1.とりあえず.then()の方法
    function doIt() {
        console.time("doIt");
        const time1 = 300;
        step1(time1)
            .then(time2 => {
                return step2(time1, time2)
                    .then(time3 => [time1, time2, time3]);
            })
            .then(times => {
                const [time1, time2, time3] = times;
                return step3(time1, time2, time3);
            })
            .then(result => {
                console.log(`result is ${result}`);
                console.timeEnd("doIt");
            });
    }
    
    doIt();
    
    とても複雑に見えます.パラメータ処理の積み重ねは、論理的にも間違いやすいです.
    2.async/awaitで書く:
    async function doIt() {
        console.time("doIt");
        const time1 = 300;
        const time2 = await step1(time1);
        const time3 = await step2(time1, time2);
        const result = await step3(time1, time2, time3);
        console.log(`result is ${result}`);
        console.timeEnd("doIt");
    }
    
    doIt();
    
    このようにロジックは非常にはっきりしています.分かりやすくて、メンテナンスも簡単です.
    参考ブログ:https://www.cnblogs.com/lpggo/p/8127604.html