1. 程式人生 > >settimeout,async,promise順序

settimeout,async,promise順序

最近被看程式寫結果的筆試題搞瘋了,最典型的當屬settimeout,async,promise混用時,哪一步該執行什麼,分不清楚。

話不多說,先上程式碼(該題為今日頭條前端開發筆試題)

        async function async1() {
            console.log("async1 start");
            await  async2();
            console.log("async1 end");
 
        }
        async  function async2() {
           console.log( 'async2');
        }
        console.log("script start");
        setTimeout(function () {
            console.log("settimeout");
        },0);
        async1();
        new Promise(function (resolve) {
            console.log("promise1");
            resolve();
        }).then(function () {
            console.log("promise2");
        });
        console.log('script end');
大家可以看一下,自己思考一下題目的輸出結果是什麼。

好啦,我們來看答案:

script start
async1 start
async2
promise1
script end
async1 end
promise2
settimeout
我們來挨個分析一下,

await  async2();//執行這一句後,輸出async2後,await會讓出當前執行緒,將後面的程式碼加到任務佇列中,然後繼續執行test()函式後面的同步程式碼
執行到setTimeout函式時,將其回撥函式加入佇列(此佇列與promise佇列不是同一個佇列,執行的優先順序低於promise)。繼續執行

建立promise物件裡面的程式碼屬於同步程式碼,promise的非同步性體現在then與catch處,所以promise1被輸出,然後將then函式的程式碼加入佇列,繼續執行同步程式碼,輸出script end。

至此同步程式碼執行完畢,開始從佇列中調取任務執行,由於剛剛提到過,setTimeout的任務佇列優先順序低於promise佇列,所以首先執行promise佇列的第一個任務,即執行async1中await後面的程式碼,輸出async1 end。

然後執行then方法的部分,輸出promise2。最後promise佇列中任務執行完畢,再執行setTimeout的任務佇列,輸出settimeout。

至此,該題的輸出結果分析完畢了,這類的執行結果可以用一句話總結,先執行同步程式碼,遇到非同步程式碼就先加入佇列,然後按入隊的順序執行非同步程式碼,最後執行setTimeout佇列的程式碼。

補充一下佇列任務優先順序:promise.Trick()>promise的回撥>setTimeout>setImmediate