上篇講異步的時候,提到了同步隊列和異步隊列的說法,其實只是一種形象的稱呼,分別表明主線程中的任務和任務隊列中的任務,那麼此篇咱們就來詳細探討這二者。html
1、來張圖感覺一下html5
若是看完以爲一臉懵逼,請繼續往下看。promise
2、解析異步
咱們仍是拿上篇的例子作解析oop
step1:f一、Promise對象實例化、f2被放入主線程的堆內存中;spa
step2:Promise對象實例化後的同步代碼塊被放入主線程的執行棧中執行,而且產生的異步任務被放入任務隊列;線程
step3:f1被放入主線程的執行棧中執行(打印「我是F1」),for循環產生的1000個定時器(異步任務)放入任務隊列;3d
step4:f2被放入主線程的執行棧中執行,連續5次;code
step5:至此,主線程的執行棧中已經沒有任務了,因而事件循環(event loop)機制從任務隊列中取出一個任務放入主線程的執行棧中執行;server
step6:等待主線程的執行棧中又沒有任務了,事件循環機制再次去任務隊列中取出任務;
step7:重複第6步。
3、任務隊列
上面提到了任務隊列,任務隊列就是等候執行的一系列任務,就比如鍋裏的飯,你只有把碗裏的飯吃完了,才能再次去鍋裏再盛一碗(不要槓!);
只有主線程的執行棧中沒有了任務,事件循環機制纔會去任務隊列拿任務去執行。
由剛開始的圖,你也看到了,任務隊列是分不一樣類別而且是有優先級的。
優先級的話,micro-task > macro-task;
對於micro-task:process.nextTick > Promise.then
對於macro-task:setTimeout > setImmediate
Promise.resolve().then(()=>{ console.log('Promise1') setTimeout(()=>{ console.log('setTimeout2') },0) }) setTimeout(()=>{ console.log('setTimeout1') Promise.resolve().then(()=>{ console.log('Promise2') }) },0)
step1:
分析:開始任務隊列裏有微任務promise1和宏任務timeout1,第一次事件循環一看有微任務,二話不說,直接拿promise1到主線程跑(實際上是跑完全部的微任務);promise1運行結果是,控制檯打印promise1,並生成一個宏任務timeout2。
step2:
分析:由於此時任務隊列裏只有宏任務,因而,根據隊列規則以及優先級(這裏只有一種宏任務,因此沒有涉及到優先級),事件循環拿timeout1去主線程跑;
timeout1運行結果,打印setTimeout1,並生成一個微任務promise2,至此第一次事件循環結束。
step3:
分析:任務隊列裏有微任務promise2和宏任務timeout2,事件循環一看有微任務,二話不說,直接拿promise2到主線程跑;
運行結果,控制檯打印promise2,此時任務隊列只剩下一個宏任務timeout2。
step4:
分析:此時任務隊列只有一個宏任務timeout2,事件循環二話不說,由於沒得挑了嘛,直接拿到主線程去跑,控制檯打印timeout2,至此結束,也是第二次事件循環結束。
因此,一次事件循環是跑完全部微任務並推一個宏任務到主線程的過程。