咱們知道js的最大特色就是單線程,就是同一時間只能作一件事。即使HTML5提出Web Worker容許JavaScript腳本建立多個線程,可是子線程徹底受主線程控制,且不得操做DOM。因此,這個新標準並無改變JavaScript單線程的本質。javascript
按照js回調事件的特性,將任務分爲同步任務和異步任務。html
任務隊列按照某種條件又能夠細分爲microtask 和 macrotask,一般咱們會稱之爲微任務和宏任務。代碼執行的優先級爲:主線程>微任務>宏任務。java
js中代碼執行的順序是:首先執行主線程中的代碼(宏任務),開始第一次循環,執行完畢後,再執行全部的微任務,而後再執行宏任務,看該宏任務中是否有微任務,若是有的話,就將全部的微任務執行完畢。再執行新的宏任務,如此不斷的反覆執行下去。
事件執行機制(即js代碼執行機制)以下圖(圖片來自ssssyoki)所示。node
//宏任務
setTimeout(function(){
console.log("我是宏任務1");
})
let p=new Promise((resolve,reject)=>{
console.log("promise1");
resolve();
});
//微任務
p.then(res=>{
console.log("我是微任務1")
});
let p2=new Promise((resolve,reject)=>{
console.log("promise2");
resolve();
});
//微任務
p2.then(res=>{
console.log("我是微任務2")
});
//宏任務
setTimeout(function(){
console.log("我是宏任務2");
})
console.log("我是主線程");
複製代碼
執行結果以下所示:promise
代碼解析:瀏覽器
宏任務 | 微任務 |
---|---|
setTimeout1 | then1 |
setTimeout2 | then2 |
//宏任務,第二次事件循環的開始
setTimeout(function() {
console.log('setTimeout1');
new Promise(function(resolve) {
console.log('setTimeout1-Promise');
resolve();
//微任務
}).then(function() {
console.log('setTimeout1-then')
})
})
new Promise(function(resolve) {
console.log('Promise');
resolve();
//微任務
}).then(function() {
console.log('then')
})
//宏任務,第三次事件循環的開始
setTimeout(function() {
console.log('setTimeout2');
new Promise(function(resolve) {
console.log('setTimeout2-promise');
resolve();
}).then(function() {
console.log('setTimeout2-then')
})
})
複製代碼
上面代碼在瀏覽器環境中的輸出結果以下所示:網絡
而在node環境中的輸出結果是這樣的,兩次執行結果還不同異步
上面的代碼在node環境中的執行結果以下所示。 函數
結果分析:oop
最後: node中的eventLoop運行機制比較複雜,因此還須要花費更多的時間去多多研究。
參考文檔
一、這一次,完全弄懂 JavaScript 執行機制
二、JavaScript 運行機制詳解:再談Event Loop
三、Eventloop不可怕,可怕的是趕上Promise
四、瀏覽器說:雖然都叫event loop,可是我和node不同