事件循环
- Node.js 是单进程单线程应用程序,但是因为 V8 引擎提供的异步执行回调接口,通过这些接口可以处理大量的并发,所以性能非常高。
- Node.js 基本上所有的事件机制都是用设计模式中观察者模式实现。
- Node.js 单线程类似进入一个while(true)的事件循环,直到没有事件观察者退出,每个异步事件都生成一个事件观察者,如果有事件发生就调用该回调函数。
事件驱动程序
- 服务器接受并处理:node.js使用事件驱动模型,当web服务器接收到请求,就把他关闭并进行处理,然后接着处理下一个请求,如此往复。
- 处理后的请求排队回到用户身边:当一个请求被完成后,他就会被放到处理队列,当他到达队列的头的时候,处理结果就返回给用户。
这个模型非常高效可扩展性非常强,因为 web服务器 一直接受请求而不等待任何读写操作。(这也称之为非阻塞式IO或者事件驱动IO)
用菜鸟教程的图如下:
穿插一下我的理解:web端、客户端等触发了事件,事件发射器(EventEmitters)就把这些事件(Enent)依次发送给服务器的接收队列,事件们一个一个排队到服务器的事件处理器(Event Handlers)那儿接受事件处理,处理完成后的事件就回到返回队列(我觉得是有两个队列的)中,排队回家(回去找触发了事件的web端、客户端响应)。
我的记忆方式:家长(客户端)把孩子(事件)送到学校(服务器),学校按家长接送顺序把孩子排队后,按顺序逐个进行教育(处理),然后教育完的就放在门口(返回的队列)排队,家长再把自个儿带过来的孩子领回去(事件的响应)(注:还挺有意思哈哈哈哈)
用简单的代码来个实例吧:(实例代码看不懂,可以再往下拉一点,看代码解析)
// 引入 events 模块
const events = require('events');
// 创建 eventEmitter(事件发射器) 对象
let eventEmitter = new events.EventEmitter();
// 创建事件处理程序
let 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("程序执行完毕。");
整个过程其实可以划分为以下四个步骤:
- 1、事件发射器的实例化(用来发射事件)
let eventEmitter = new events.EventEmitter(); - 2、绑定事件,并编写接收到该事件作何响应
方法1、接收到名为’connection’的事件(可以取别的名字),就触发connectHandler回调函数(名字也是任取)
//事件处理函数(回调函数)
let connectHandler = function connected() {
console.log('连接成功。');
};
//绑定事件connection触发connectHandler
eventEmitter.on('connection', connectHandler);
方法2、使用匿名函数绑定名为’data_received’的事件,并把处理的回调直接用匿名方式写下)
eventEmitter.on('data_received', function(){
console.log('数据接收成功。');
});
- 3、触发事件
eventEmitter.emit('connection'); //触发connection事件
// 触发 data_received 事件
eventEmitter.emit('data_received');
- 4.响应请求(触发事件处理)
连接成功是触发了connection事件绑定的回调函数,数据接收成功是触发了data_received绑定的回调函数。