setTimeout,javascript
setInterval,java
setImmediate,node
I/O,typescript
UI rendering.promise
process.nextTick, 函數
Promise(原生),spa
Object.observe,code
MutationObserverorm
備註:同時須要注意的是,在 ES 當中稱 microtask 爲 「jobs」。好比 ES6標準 8.4節當中的 「EnqueueJob」 意思指添加一個 microtask。server
setImmediate(function(){
console.log(1);
},0);
setTimeout(function(){
console.log(2);
},0);
new Promise(function(resolve){
console.log(3);
resolve();
console.log(4);
}).then(function(){
console.log(5);
});
console.log(6);
process.nextTick(function(){
console.log(7);
});
console.log(8);
//輸出結果是3 4 6 8 7 5 2 1
看看另外一題目
setTimeout(()=>{ console.log('A'); },0); var obj={ func:function () { setTimeout(function () { console.log('B') },0); return new Promise(function (resolve) { console.log('C'); resolve(); }) } }; obj.func().then(function () { console.log('D') }); console.log('E');
一、首先 setTimeout A 被加入到事件隊列中 ==> 此時macrotasks中有[‘A’];
二、obj.func()執行時,setTimeout B 被加入到事件隊列中 ==> 此時macrotasks中有[‘A’,‘B’];
三、接着return一個Promise對象,Promise 新建後當即執行 執行console.log('C'); 控制檯首次打印‘C’;
四、而後,then
方法指定的回調函數,被加入到microtasks隊列,將在當前腳本全部同步任務執行完纔會執行。 ==> 此時microtasks中有[‘D’];
五、而後繼續執行當前腳本的同步任務,故控制檯第二次輸出‘E’;
六、此時全部同步任務執行完畢,如上所述先檢查microtasks隊列,完成其中全部任務,故控制檯第三次輸出‘D’;
七、最後再執行macrotask的任務,而且按照入隊列的時間順序,控制檯第四次輸出‘A’,控制檯第五次輸出‘B’。
setTimeout(function timeout () { console.log('timeout'); },0); setImmediate(function immediate () { console.log('immediate'); });
結果
immediate
timeout
setInterval(function timeout () {
console.log('setInterval');
},0);
setTimeout(function timeout () {
console.log('timeout');
},0);
setImmediate(function immediate () {
console.log('immediate');
});
結果:
immediate
setInterval
timeout
setInterval
setTimeout(function timeout () { console.log('timeout'); },0);setInterval(function timeout () { console.log('setInterval'); },0);
timeout
setInterval
setTimeout(function timeout () { console.log('timeout'); },0); setImmediate(function immediate () { console.log('immediate'); }); process.nextTick(function immediate () { console.log('nickTick'); });
結果
nextTick timeout immediate
process.nextTick像是一個插入的tick. 生成了一個新的週期. 說白了, 是一個插隊行爲.
關於micro-task和macro-task的執行順序,可看下面這個例子(來自《深刻淺出Node.js》):
//加入兩個nextTick的回調函數
process.nextTick(function () {
console.log('nextTick延遲執行1');
});
process.nextTick(function () {
console.log('nextTick延遲執行2');
});
// 加入兩個setImmediate()的回調函數
setImmediate(function () {
console.log('setImmediate延遲執行1');
// 進入下次循環
process.nextTick(function () {
console.log('強勢插入');
});
});
setImmediate(function () {
console.log('setImmediate延遲執行2');
});
console.log('正常執行')
書中給出的執行結果是:
正常執行
nextTick延遲執行1
nextTick延遲執行2
setImmediate延遲執行1
強勢插入
setImmediate延遲執行2
process.nextTick在兩個setImmediate之間強行插入了。
但運行這段代碼發現結果倒是這樣:
正常執行 nextTick延遲執行1 nextTick延遲執行2 setImmediate延遲執行1 setImmediate延遲執行2 強勢插入
樸老師寫那本書的時候,node最新版本爲0.10.13,而個人版本是6.x