最近在學習nodejs,看到了異步這塊,就整理了下Node中幾個異步APIjavascript
定時器:
setTimeout和setInterval與瀏覽器中的API是一致的,分別用於單次和屢次定時執行任務。他們的實現原理和異步I/O比較相似,只是不須要I/O線程池的參與。調用他們建立的定時器會被插入到定時器觀察者內部的一個紅黑樹中。每次Tick執行的時候,會從該紅黑樹中迭代取出定時器對象,檢查是否超過定時時間,若是超過,就造成一個事件,它的回調函數將當即執行。java
問題:並不是精確,儘管事件循環很是快,可是若是某一次循環佔用的時間比較多,那麼下次循環時,它也許已經超時好久了。node
process.nextTick()
不少人會爲了當即異步執行一個任務,會這樣調用setTimeout()來達到所需的效果。瀏覽器
setTimeout(function () {
// TODO
}, 0)
複製代碼
因爲事件循環的特色,定時器的精確度不夠。而事實上,採用定時器須要動用紅黑樹,建立定時器對象和迭代等操做,而setTimeout(fn, 0)較爲浪費性能。而process.nextTick()方法的操做相對較爲輕量,具體代碼以下:bash
process.nextTick = function (callback) {
if( process._exiting ) return;
if( tickDepth >= process.maxTickDepth ){
maxTickWarn();
}
var tock = { callback: callback};
if( process.domain ) tock.domain = process.domain;
nextTickQueue.push( tock );
if( nextTickQueue.length ) {
process._needTickCallback();
}
}
複製代碼
每次調用process.nextTick()方法,只會將回調函數放入隊列中,在下一輪Tick時取出執行。定時器中採用紅黑樹的操做時間複雜度爲O(lg(n)), nextTick()的時間複雜度爲O(1)。相對之下,process.nextTick()更加有效。dom
setImmediate()
setImmdiate()方法與process.nextTick()方法相似,都是將回調函數延遲執行。異步
process.nextTick( function () {
console.log("延遲執行!");
});
console.log("正常執行!");
// 結果:
// 正常執行
// 延遲執行
複製代碼
用setImmediate()實現:函數
setImmediate( function () {
console.log("延遲執行")
});
console.log("正常執行");
// 結果:
// 正常執行
// 延遲執行
複製代碼
放在一塊兒執行:性能
proccess.nextTick( function () {
console.log("nextTick");
});
setImmediate( function () {
console.log("immediate");
});
console.log("正常執行");
// 結果:
// 正常執行
// nextTick
// immediate
複製代碼
process.nextTick()中的回調函數優先級高於setImmediate(). process.nextTick()屬於idle觀察者,setImmediate()屬於check觀察者。在每個輪循環檢查中,idle觀察者先於I/O觀察者,I/O觀察者先於check觀察者。學習
三者的執行順序爲process.next() 先於 定時器 先於 setImmediate()