近日在論壇上看到一篇文章講node和谷歌瀏覽器的eventloop的區別,由於看到寫的還不錯,我表示了確定。但沒過多久一位壇友卻說node11結果不同,我說怎麼可能不同。接着壇友貼了個代碼,我試着運行了一下,啪啪打臉!node
先上被啪啪打臉的代碼:git
setTimeout(() => { console.log('timer1'); Promise.resolve().then(function() { console.log('promise1'); }); }, 0); setTimeout(() => { console.log('timer2'); Promise.resolve().then(function() { console.log('promise2'); }); }, 0); 複製代碼
瞭解node的eventloop的同窗應該會這樣想:github
那麼若是機器運行良好就是如下結果:promise
timer1
timer2
promise1
promise2
複製代碼
node10運行結果確實是這樣,是沒問題的。但node11運行後竟然是:瀏覽器
timer1
promise1
timer2
promise2
複製代碼
挺吃驚的,但吃驚事後仍是仔細去翻node的修改日誌,在node 11.0 的修改日誌裏面發現了這個:markdown
而後分別看了20002和22842的PR,發如今 #22842 在lib/timers.js裏面有如下增長:異步
這兩個是什麼意思呢?oop
提示一下runNextTicks()就是process._tickCallback()。用過的可能知道這個就是除了處理一些異步鉤子,而後就是執行微任務隊列的。因而我增長了兩行process._tickCallback()在setTimeout方法尾部,再使用node10運行,效果果真和node11一致,代碼以下:spa
setTimeout(() => { console.log('timer1'); Promise.resolve().then(function() { console.log('promise1'); }); process._tickCallback(); // 這行是增長的! }, 0); setTimeout(() => { console.log('timer2'); Promise.resolve().then(function() { console.log('promise2'); }); process._tickCallback(); // 這行是增長的! }, 0); 複製代碼
固然是爲了和瀏覽器更加趨同。日誌
瞭解瀏覽器的eventloop可能就知道,瀏覽器的宏任務隊列執行了一個,就會執行微任務。
簡單的說,能夠把瀏覽器的宏任務和node10的timers比較,就是node10只有所有執行了timers階段隊列的所有任務才執行微任務隊列,而瀏覽器只要執行了一個宏任務就會執行微任務隊列。
如今node11在timer階段的setTimeout,setInterval...和在check階段的immediate都在node11裏面都修改成一旦執行一個階段裏的一個任務就馬上執行微任務隊列。
因此在生產環境建議仍是不要特地的去利用node和瀏覽器不一樣的一些特性。即便是node和瀏覽器相同的特性,但規範沒肯定的一些特性,也建議當心使用。不然一次小小的node升級可能就會形成一次線上事故,而不僅是啪啪打臉這麼簡單了。