process
process在nodejs中是一個全局的對象开睡,不需要require()可以直接使用篇恒,process中主要包含以下信息:
- 進程基礎(chǔ)信息
- 進程 Usage
- 進程級事件
- 依賴模塊/版本信息
- OS 基礎(chǔ)信息
- 賬戶信息
- 信號收發(fā)
- 三個標(biāo)準(zhǔn)流
process.nextTick
Node.js是單線程的胁艰,除了系統(tǒng)IO之外,在它的事件輪詢過程中腾么,同一時間只會處理一個事件哮翘。你可以把事件輪詢想象成一個大的隊列毛秘,在每個時間點上,系統(tǒng)只會處理一個事件艰匙。即使你的電腦有多個CPU核心员凝,你也無法同時并行的處理多個事件奋献。但也就是這種特性使得node.js適合處理I/O型的應(yīng)用,不適合那種CPU運算型的應(yīng)用糖埋。在每個I/O型的應(yīng)用中,你只需要給每一個輸入輸出定義一個回調(diào)函數(shù)即可征候,他們會自動加入到事件輪詢的處理隊列里祟敛。當(dāng)I/O操作完成后馆铁,這個回調(diào)函數(shù)會被觸發(fā)。然后系統(tǒng)會繼續(xù)處理其他的請求畔裕。
在這種處理模式下乖订,process.nextTick()的意思就是定義出一個動作乍构,并且讓這個動作在下一個事件輪詢的時間點上執(zhí)行。
- 多個事件里交叉執(zhí)行CPU運算密集型的任務(wù)
由于javascript是單進程的哥遮,當(dāng)一個cpu被一個任務(wù)任務(wù)跑滿時眠饮,它是不能執(zhí)行其他任務(wù)的铜邮,在web服務(wù)中,這點甚至是致命扔茅,如果它被一個cpu密集的任務(wù)占滿召娜,那就不能相應(yīng)其他的請求了惊楼,程序相當(dāng)于“假死”。
var http = require('http');
function compute() {
// performs complicated calculations continuously
// ...
process.nextTick(compute);
//setTimeout(() => compute(), 0);
}
http.createServer(function(req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World');
}).listen(5000, '127.0.0.1');
compute();
如上例子璃诀,在這個過程中屯断,如果有新的http請求進來,事件循環(huán)機制會先處理新的請求氧秘,然后再調(diào)用compute()丸相。反之彼棍,如果你把compute()放在一個遞歸調(diào)用里,那系統(tǒng)就會一直阻塞在compute()里弛作,無法處理新的http請求了
- 保持回調(diào)函數(shù)異步執(zhí)行的原則
當(dāng)你給一個函數(shù)定義一個回調(diào)函數(shù)時映琳,你要確保這個回調(diào)是被異步執(zhí)行的萨西。
function asyncReal(data, callback) {
process.nextTick(function() {
callback(data === 'foo');
});
}
- 事件觸發(fā)過程中
function StreamLibrary(resourceName) {
var self = this;
process.nextTick(function() {
self.emit('start');
});
// read from the file, and for every chunk read, do:
this.emit('data', chunkRead);
}
var stream = new StreamLibrary('fooResource');
stream.on('start', function() {
console.log('Reading has started');
});
stream.on('data', function(chunk) {
console.log('Received: ' + chunk);
});
process.nextTick()會使得start事件不會被立即觸發(fā)谎脯,因為如果是被立即觸發(fā)源梭,事件的回調(diào)函數(shù)還沒有準(zhǔn)備好稍味,所以在客戶端根本無法接收到這個事件
Tick
在libev中的event loop 的每次迭代仲闽,在nodejs 中就叫做 “Tick”。javascript是單進程運行的,具體到nodejs中验庙,就是如圖運行粪薛。
┌───────────────────────┐
┌─>│ timers │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
│ │ I/O callbacks │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
│ │ idle, prepare │
│ └──────────┬────────────┘ ┌───────────────┐
│ ┌──────────┴────────────┐ │ incoming: │
│ │ poll │<─────┤ connections, │
│ └──────────┬────────────┘ │ data, etc. │
│ ┌──────────┴────────────┐ └───────────────┘
│ │ check │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
└──┤ close callbacks │
└───────────────────────┘
- timers: this phase executes callbacks scheduled by setTimeout() and setInterval().
- I/O callbacks: executes almost all callbacks with the exception of close callbacks, the ones scheduled by timers, and setImmediate().
- idle, prepare: only used internally.
- poll: retrieve new I/O events; node will block here when appropriate.
- check: setImmediate() callbacks are invoked here.
close callbacks: e.g. socket.on('close', ...).