process
process在nodejs中是一个全局的对象,不需要require()可以直接使用,process中主要包含以下信息:
- 进程基础信息
- 进程 Usage
- 进程级事件
- 依赖模块/版本信息
- OS 基础信息
- 账户信息
- 信号收发
- 三个标准流
process.nextTick
Node.js是单线程的,除了系统IO之外,在它的事件轮询过程中,同一时间只会处理一个事件。你可以把事件轮询想象成一个大的队列,在每个时间点上,系统只会处理一个事件。即使你的电脑有多个CPU核心,你也无法同时并行的处理多个事件。但也就是这种特性使得node.js适合处理I/O型的应用,不适合那种CPU运算型的应用。在每个I/O型的应用中,你只需要给每一个输入输出定义一个回调函数即可,他们会自动加入到事件轮询的处理队列里。当I/O操作完成后,这个回调函数会被触发。然后系统会继续处理其他的请求。
在这种处理模式下,process.nextTick()的意思就是定义出一个动作,并且让这个动作在下一个事件轮询的时间点上执行。
- 多个事件里交叉执行CPU运算密集型的任务
由于javascript是单进程的,当一个cpu被一个任务任务跑满时,它是不能执行其他任务的,在web服务中,这点甚至是致命,如果它被一个cpu密集的任务占满,那就不能相应其他的请求了,程序相当于“假死”。
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请求进来,事件循环机制会先处理新的请求,然后再调用compute()。反之,如果你把compute()放在一个递归调用里,那系统就会一直阻塞在compute()里,无法处理新的http请求了
- 保持回调函数异步执行的原则
当你给一个函数定义一个回调函数时,你要确保这个回调是被异步执行的。
function asyncReal(data, callback) {
process.nextTick(function() {
callback(data === 'foo');
});
}
- 事件触发过程中
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事件不会被立即触发,因为如果是被立即触发,事件的回调函数还没有准备好,所以在客户端根本无法接收到这个事件
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', ...).