Node.js事件循环
参考https://www.runoob.com/nodejs/nodejs-event-loop.html
Node.js本身是单进程单线程的应用程序,但是V8引擎提供了可异步执行的回调接口,通过这些接口可以处理大量的并发。
- Node.js几乎每一个API都持支回调函数。
- Node.js几乎所有事件机制都是使用观察者模式实现。
- Node.js的单线程类似于进入了一个while(true)事件循环,直到没有事件观察者才会退出循环。
- 每个异步事件都会生成一个事件观察者,如果有事件发生就调用该回调函数。
事件驱动程序
Node.js使用事件驱动模型,当服务器接收到请求,就先把它关闭进行处理,然后去处理下一个请求。当这个请求完成,它会被放回处理队列,当到达队列开头,这个处理结果就会被返回给用户。
这个模型非常高效且可拓展性非常强,因为服务器一直在接收请求而不等待任何读写等IO操作(即非阻塞式IO或事件驱动IO)。
在事件驱动模型中,会产生一个主循环来用于监听事件(类似于上面提到的while(trur)事件循环),每当检测到异步事件就会产生一个事件观察者并触发回调函数。
事件相当于一个主题(Subject),所有注册到这个事件上的处理函数相当于观察者(Observer)。
Node.js有多个内置的事件,通过引入events模块并实例化EventEmitter类来绑定和监听事件:
// 引入events模块
var events = require('events');
// 创建eventEmitter对象
var eventEmitter = new events.EventEmitter();
然后是绑定事件处理程序:
// 绑定事件处理程序
eventEmitter.on('eventName', eventHandler);
使得我们可以通过程序来触发该事件:
// 触发事件
eventEmitter.emit('eventName');
实例:
创建main.js,代码如下:
// 引入events模块
var events = require('events');
// 创建eventEmitter对象
var eventEmitter = new events.EventEmitter();
// 创建事件处理程序
var connectHandler = function connected(){
console.log('连接成功。');
// 触发data_received事件
eventEmitter.emit('data_received');
}
// 绑定connection事件处理程序
eventEmitter.on('connection', connectHandler);
// 使用匿名函数绑定data_received事件
eventEmitter.on('data_received', function(){
console.log('数据接收成功。');
});
// 触发connection事件
eventEmitter.emit('connection');
console.log('程序执行完毕。');
执行结果:
Node应用是如何工作的?
在Node应用程序中,执行异步操作的函数将回调函数作为最后一个参数,回调函数接收错误对象作为第一个参数。
例如,使用input.txt作为可读取的文本文件,内容如下:
菜鸟官网地址:www.runoob.com
创建main.js文件,代码如下:
var fs = require('fs');
fs.readFile('input.txt', function(err, data){
if(err){
console.log(err.stack);
return;
}
console.log(data.toString());
});
console.log('执行完毕');
结果:
- 上面的程序中的readFile()是异步读取文件的函数,如果执行过程中发生错误,错误对象err会作为回调函数的第一个参数被传入,如果没有错误则跳过。
- 如果input.txt不存在,就会发生错误,这时错误对象的栈信心会被打印出来: