在javascript中我們了解到了setTimeout和setInterVal函數事件隊列(任務隊列)的相關知識,除了setTimeout和setInterval這兩個方法外,Node.js還提供了另外兩個與"任務隊列"有關的方法:process.nextTick和setImmediate。它們可以幫助我們加深對"任務隊列"的理解。
setTimeout()
首先我們看看setTimeout(setInterVal和setTimeout函數區別只是執行次數)函數,需要注意的是,setTimeout()只是將事件插入了"任務隊列",必須等到當前代碼(執行棧)執行完,主線程才會去執行它指定的回調函數。要是當前代碼耗時很長,有可能要等很久,所以並沒有辦法保證,回調函數一定會在setTimeout()指定的時間執行。
1 setTimeout(function(){console.log('0')},0);//意思是回調函數加入事件隊列的隊尾,主線程和事件隊列的函數執行完成之后立即執行定時器的回調函數,如果定時器的定時是相同的,就按定時器回調函數的先后順序來執行。 2 console.log(1); 3 setTimeout(function(){console.log(2);},1000); 4 setTimeout(function(){console.log(4);},1000); 5 console.log(3); 6 //1 3 0 2 4
setImmediate()
setImmediate()是將事件插入到事件隊列尾部,主線程和事件隊列的函數執行完成之后立即執行setImmediate指定的回調函數,和setTimeout(fn,0)的效果差不多,但是當他們同時在同一個事件循環中時,執行順序是不定的。另外setTimeout和setImmediate也有一定的區別(還在探索...),在實際工作中我們其實她們的區別貌似不明顯,請高手指出感激不盡
1 console.log('1'); 2 3 setImmediate(function () { 4 console.log('2'); 5 }); 6 7 setTimeout(function () { 8 console.log('3'); 9 },0); 10 11 process.nextTick(function () { 12 console.log('4'); 13 }); 14 15 //1 4 2 3也可能是1 4 3 2
process.nextTick()
process.nextTick()方法可以在當前"執行棧"的尾部-->下一次Event Loop(主線程讀取"任務隊列")之前-->觸發process指定的回調函數。也就是說,它指定的任務總是發生在所有異步任務之前,當前主線程的末尾。(nextTick雖然也會異步執行,但是不會給其他io事件執行的任何機會)
1 process.nextTick(function A() { 2 console.log(1); 3 process.nextTick(function B(){console.log(2);}); 4 }); 5 6 setTimeout(function C() { 7 console.log(3'); 8 }, 0) 9 // 1 10 // 2 11 // 3
當然這樣也是一樣的:
setTimeout(function C() { console.log(3'); }, 0) process.nextTick(function A() { console.log(1); process.nextTick(function B(){console.log(2);}); }); // 1 // 2 // 3
當然這樣還是一樣的:
setTimeout(function C() { console.log(3'); }, 0) process.nextTick(function A() { process.nextTick(function B(){console.log(2);}); console.log(1); }); // 1 // 2 // 3
最后process.maxTickDepth()的缺省值是1000,如果超過會報exceed callback stack。官方認為在遞歸中用process.nextTick會造成飢餓event loop,因為nextTick沒有給其他異步事件執行的機會,遞歸中推薦用setImmediate
foo = function(bar) { console.log(bar); return process.nextTick(function() { return f(bar + 1); }); }; setImmediate(function () { console.log('1001'); }); foo(1);//注意這樣不會輸出1001,當遞歸執行到1000次是就會報錯exceed callback stack,
/*
foo = function(bar) {
console.log(bar);
if(bar>1000){
return;
}
return process.nextTick(function() { return f(bar + 1); }); }; setImmediate(function () { console.log('1001'); }); foo(1);
*/