js是單執行緒
javascript在最初設計時設計成了單執行緒,為什麼不是多執行緒呢?如果多個執行緒同時操作DOM豈不會很混亂?比如,假定JavaScript同時有兩個執行緒,一
個執行緒在某個DOM節點上新增內容,另一個執行緒刪除了這個節點,這時瀏覽器應該以哪個執行緒為準?這裡所謂的單執行緒指的是主執行緒是單執行緒的,所以在Node
中主執行緒依舊是單執行緒的。
瀏覽器的event-loop
執行棧與任務佇列
(1)所有同步任務都在主執行緒上執行,形成一個執行棧。
(2)主執行緒之外,還存在一個"任務佇列"(task queue)。只要非同步任務有了執行結果,就在"任務佇列"之中放置
一個事件。
(3)一旦"執行棧"中的所有同步任務執行完畢,系統就會讀取"任務佇列",看看裡面有哪些事件。那些對應的非同步
任務,於是結束等待狀態,進入執行棧
,開始執行。
(4)主執行緒不斷重複上面的第三步。
複製程式碼
任務佇列分為macro-task(巨集任務)和micro-task(微任務)。
macro-task(巨集任務): setTimeout, setInterval, setImmediate, I/O等
micro-task(微任務): process.nextTick, 原生Promise(有些實現的promise將then方法放到了巨集任務中),Object.observe(已廢棄), MutationObserver等
console.log(1);
console.log(2);
Promise.resolve().then(function(){
console.log('promise')
});
setTimeout(function(){
console.log('setTimeout1')
Promise.resolve().then(function(){
console.log('promise')
});
})
setTimeout(function(){
console.log('setTimeout2');
});
複製程式碼
結果:
1
2
promise
setTimeout1
promise
setTimeout2
瀏覽器 會先執行同步程式碼 ===> 然後檢視任務佇列 ===> 先執行micro-task(微任務) ===> 在執行macro-task(巨集任務)
個人理解: 有微先走微,沒微就走巨集。複製程式碼
Nodejs的event-loop
Nodejs與瀏覽器的 event-loop有些不同
nodeJS中的巨集任務和微任務在瀏覽器的基礎上有新增了幾個
微任務
then
nextTick
messageChannel
mutationObersve
巨集任務
setTimeout
setInterval
setImmediate
nodejs的event-loop圖解
當node執行完同步程式碼時就會執行上圖的順序
console.log(1);
console.log(2);
Promise.resolve().then(function(){
console.log('promise')
});
setTimeout(function(){
console.log('setTimeout1')
Promise.resolve().then(function(){
console.log('promise')
});
})
setTimeout(function(){
console.log('setTimeout2');
});
複製程式碼
node環境裡的執行順序
1
2
promise
setTimeout1
setTimeout2
promise
node 執行完同步程式碼 之後會先查詢 微任務佇列 然後逐一清空 微任務 然後走timer 清空timer(巨集任務)複製程式碼
node裡的的 nextTick 與 setImmediate
process.nextTick(function(){ console.log('nextTick')});setImmediate(function(){ console.log('immediate')});
nextTickimmediate因為 nextTick是微任務 所以nextTick先執行複製程式碼