一個 JavaScript 引擎會常駐於內存中,它等待着咱們把JavaScript 代碼或者函數傳遞給它執行javascript
在 ES3 和更早的版本中,JavaScript 自己尚未異步執行代碼的能力,引擎就把代碼直接順次執行了,異步任務都是宿主環境(瀏覽器)發起的(setTimeout、AJAX等)。html
在 ES5 以後,JavaScript 引入了 Promise,這樣,不須要瀏覽器的安排,JavaScript 引擎自己也能夠發起任務了java
js爲單線程,js引擎中負責解析執行js代碼的線程只有一個(主線程),即每次只能作一件事,其餘IO操做放入任務隊列等待執行,異步過程當中,工做線程在異步操做完成後須要通知主線程。那麼這個通知機制是利用消息隊列和事件循環(EventLoop)實際上,主線程只會作一件事情,就是從消息隊列裏面取消息、執行消息,再取消息、再執行。當消息隊列爲空時,就會等待直到消息隊列變成非空。並且主線程只有在將當前的消息執行完成後,纔會去取下一個消息
node:node.js單線程只是一個js主線程,本質上的異步操做仍是由線程池完成的,node將全部的阻塞操做都交給了內部的線程池去實現,自己只負責不斷的往返調度,並無進行真正的I/O操做,從而實現異步非阻塞I/O,這即是node單線程的精髓之處了。node
微任務:git
宏任務github
過程promise
每次事件循環都包含了6個階段瀏覽器
setTimeout
、setInterval
)的回調setImmediate()
的回調socket
的 close
事件回調
Node 會去檢查有無已過時的timer,若是有則把它的回調壓入timer的任務隊列中等待執行網絡
技術上來講,poll 階段控制 timers 何時執行。異步
poll 階段
poll 階段主要有2個功能:
執行過程:當event loop進入 poll 階段,而且 沒有設定的timers(there are no timers scheduled),會發生下面兩件事之一:
若是 poll 隊列不空,event loop會遍歷隊列並同步執行回調,直到隊列清空或執行的回調數到達系統上限;
若是 poll 隊列爲空,則發生如下兩件事之一:
setImmediate()
會致使event loop阻塞在poll階段,這樣以前設置的timer豈不是執行不了了?因此咧,在poll階段event loop會有一個檢查機制,檢查timer隊列是否爲空,若是timer隊列非空,event loop就開始下一輪事件循環,即從新進入到timer階段。process.nextTick()
process.nextTick()
,會致使出現I/O starving(飢餓)setImmediate
setTimeout(()=>{ console.log('timer1') Promise.resolve().then(function() { console.log('promise1') }) }, 0) setTimeout(()=>{ console.log('timer2') Promise.resolve().then(function() { console.log('promise2') }) }, 0) //瀏覽器: timer1 promise1 timer2 promise2 // node timer1 timer2 promise1 promise2
http://lynnelv.github.io/img/...
http://lynnelv.github.io/img/...
https://juejin.im/post/5b61d8...
https://yq.aliyun.com/article...
https://juejin.im/post/5b1e55...