JS的運行機制到底是什麼?
先給大家來段代碼,看大家能否知道輸出的結果
console.log('1');
setTimeout(function() {
console.log('2');
process.nextTick(function() {
console.log('3');
})
new Promise(function(resolve) {
console.log('4');
resolve();
}).then(function() {
console.log('5')
})
})
process.nextTick(function() {
console.log('6');
})
new Promise(function(resolve) {
console.log('7');
resolve();
}).then(function() {
console.log('8')
})
setTimeout(function() {
console.log('9');
process.nextTick(function() {
console.log('10');
})
new Promise(function(resolve) {
console.log('11');
resolve();
}).then(function() {
console.log('12')
})
})
瞭解js的同步和異步
先要明白js是單線程語言,所有的js多線程都是用單線程模擬出來的
導圖要表達的內容用文字來表述的話:
- 同步和異步任務分別進入不同的執行"場所",同步的進入主線程,異步的進入Event Table並註冊函數。
- 當指定的事情完成時,Event Table會將這個函數移入Event Queue。
- 主線程內的任務執行完畢為空,會去Event Queue讀取對應的函數,進入主線程執行。
- 上述過程會不斷重複,也就是常説的Event Loop(事件循環)。
我們不禁要問了,那怎麼知道主線程執行棧為空啊?js引擎存在monitoring process進程,會持續不斷的檢查主線程執行棧是否為空,一旦為空,就會去Event Queue那裏檢查是否有等待被調用的函數。
用我自己的話説:
打開一個js代碼,先執行同步任務,遇到異步任務,把異步任務放到隊列中,等同步任務執行完之後,在執行異步任務,非常好理解
其實這個不太準確,同步和異步是廣義範圍內的,如果要在精細一點,就分為宏任務和微任務,後面會講
那些是同步?那些是異步?
異步:setTimeout(),setInterval(),Promise,process.nextTick(callback) 等
同步:剩下的基本都是同步的
宏任務和微任務
- macro-task(宏任務):包括整體代碼script,setTimeout,setInterval,dom事件,ajax請求
- micro-task(微任務):Promise,process.nextTick,asycn/await
結合圖片和上面的文字可以看出
- 整個script就是一個宏任務,所以先把script放入到宏任務中
- 遇到setTimeout,setInterval,把它們也放到宏任務中。遇到Promise,process.nextTick,把它們放到微任務中
- 先執行宏任務,執行完成,執行微任務,完成之後再執行宏任務,知道把所有的任務都執行完成
接下來,看上面代碼的輸出結果
安裝宏任務和微任務的執行順序,一點一點來
- 把js中所有是宏任務的代碼都放到宏隊列中,所有的微任務都放到微隊列中,能直接輸出的直接輸出
- 先輸出1
- 遇到setTimeout(),把它放到宏任務,有兩個,先標記為set1,set2
- 遇到process.nextTick,把執行的函數放到微任務
- 遇到promise,只把.then的函數放到微任務,所以輸出7
- 第一步完成後輸出1,7
- 然後執行微任務
- 有兩個微任務,要注意先後順序,從上到下
- 執行process.nextTick,輸出6
- 執行promise.then,輸出8
- 第二步完成後輸出6,8
- 微任務執行完,在執行宏任務,有兩個宏任務,set1,set2
- 接下來和上面的操作是一樣的,先執行宏任務set1
- 輸出2,4
- 把promise.then和process.nextTick放入微任務
- 執行微任務,輸出3,5
- 第三步完成後輸出2,4,3,5
- 再執行宏任務set2
- 輸出9,11
- 把promise.then和process.nextTick放入微任務
- 執行微任務,輸出10,12
- 第四步完成後輸出9,11,10,12
最終結果1,7,6,8,2,4,3,5,9,11,10,12
不知道各位小夥伴答案對不對呢?