概述
文章目录
- 一、Node.js事件循环
- 二、事件驱动程序
- 三、事件触发器
- 1、EventEmitter类
- 2、事件触发器的方法
- (1)EventEmitter类的on方法
- (2)EventEmitter类的once方法
- (3)使用removeListener方法取消事件处理函数
- (4)自定义事件并将其触发
- 四、错误事件
一、Node.js事件循环
Node.js是单进程单线程
应用程序,但是因为V8引擎提供的异步执行回调接口,通过这些接口可以处理大量的并发,所以性能非常高。
Node.js几乎每一个API都是支持回调函数
的。
Node.js基本上所有的事件机制都是用设计模式中观察者模式实现
Node.js单线程类似进入一个while(true)的事件循环,直到没有事件观察者退出,每个异步事件都生成一个事件观察者,如果有事件发生就调用该回调函数
二、事件驱动程序
Node.js使用事件驱动模型
,当Web server接受到请求,就把它关闭然后进行处理,然后去服务下一个web请求。当这个请求完成后,它被放回处理队列,当到达队列开头,这个结果被返回给用户。
这个模型非常高效可扩展性非常强,因为webserver一直接受请求而不等待任何读写操作。(这也称为非阻塞式IO或者事件驱动IO)
在事件驱动模型中,会生成一个主循环来监听事件,当检测到事件时触发回调函数。
注意:线程是整个程序的最小单位,即一个程序就是一个进程,一个进程里至少要运行一个线程。
在Node.js的事件机制中主要有三类角色:事件(Event)、事件发射器(EventEmitter)、事件监听器(EventListener)
Node.js 有多个内置的事件,我们可以通过引入 events 模块,并通过实例化 EventEmitter 类来绑定和监听事件。例如:
//引入events模块
var events = require('events');
//创建eventEmitter对象
var eventEmitter = new events.EventEmitter();
//绑定事件及事件的处理程序
eventEmitter.on('eventName',eventHandler);
//触发事件
eventEmitter.emit('eventName');
三、事件触发器
Node.js 的大部分核心 API 都是围绕惯用的异步事件驱动架构构建的,在该架构中,某些类型的对象(称为"触发器")触发命名事件,使 Function 对象(“监听器”)被调用。
EventEmitter类
:事件发射器,也叫事件触发器,所有可能触发事件的对象都是一个集成了EventEmitter类的子类的实例对象,这些对象暴露了 eventEmitter.on() 函数,允许将一个或多个函数绑定到对象触发的命名事件。 通常,事件名称是驼峰式字符串,但也可以使用任何有效的 JavaScript 属性键。
当 EventEmitter 对象触发事件时,所有绑定到该特定事件的函数都会被同步地调用。 被调用的监听器返回的任何值都将被忽略和丢弃。
EventEmitter 按照注册的顺序同步
地调用所有监听器。 这确保了事件的正确排序,并有助于避免竞争条件和逻辑错误。 在适当的时候,监听器函数可以使用 setImmediate() 或 process.nextTick() 方法切换到异步的操作模式。
1、EventEmitter类
EventEmitter 类由 events 模块定义和暴露:
const EventEmitter = require('events');
所有的 EventEmitter,当添加新的监听器时触发事件 ‘newListener’,当删除现有的监听器时触发事件 ‘removeListener’。
2、事件触发器的方法
在Node.js中,为EventEmitter类定义了许多方法,所有与对象的事件处理函数的绑定及解除相关的处理均依靠这些方法的调用来执行。
常用方法:(event
:代表事件名,listener
:代表事件处理函数)
方法名与参数 | 描述 |
---|---|
addListener(event,listener) | 事件监听函数,emitter.on(eventName, listener) 的别名。 |
on(event, listener) | 对指定对象绑定事件处理函数(addListener方法的别名) |
once(event, listener) | 对指定对象指定只执行一次的事件处理函数 |
removeListener(event, listener) | 删除事件 |
setMaxListeners(n) | 指定对象处理函数的最大数量,n为正数值,代表最大的可指定事件处理函数的数量 |
listeners(event) | 获取指定对象的所有事件处理函数 |
emit(event, [arg1], [arg2], […]) | 手动触发指定事件 |
newListener(event,Listener) | 添加新的监听器 |
(1)EventEmitter类的on方法
emitter.on(eventName, listener);
eventName < string > | < symbol > 事件的名称。
listener < Function > 回调函数
返回: < EventEmitter >
将 listener 函数添加到名为 eventName 的事件的监听器数组的末尾。 不检查是否已添加 listener。 多次调用传入相同的 eventName 和 listener 组合将导致多次添加和调用 listener。默认情况下,事件监听器按添加顺序调用。
例1:当服务器接收到客户端请求时,在控制台窗口中输出客户端请求的目标地址(URL地址),并使用响应对象的end方法立即结束响应。
const http = require('http');
//创建服务器对象
let server = http.createServer();
//给服务器对象绑定事件request
server.on('request',function (req,res){
//输出请求对象的地址
console.log('请求地址:',req.url);
//服务器关闭和客户端的连接,并发送响应信息
res.end('hello world');
})
//服务器启动监听
server.listen(8089,'127.0.0.1');
例2:也可以通过多个on方法的执行来对同一个事件绑定多个事件处理函数。
var http = require("http");
//创建服务器对象
var server = http.createServer();
//给服务器对象绑定多个事件处理函数
server.on('request',function(req,res){
console.log('接收到客户端请求')
})
server.on("request",function(req,res){
console.log('处理客户端请求')
console.log(req.url);
res.end('hello');
})
server.on('request',function(req,res){
console.log('发送响应完毕')
})
//服务器启动监听
server.listen(1337,"127.0.0.1");
(2)EventEmitter类的once方法
emitter.once(eventName, listener);
eventName < string > | < symbol > 事件的名称。
listener < Function > 回调函数
返回: < EventEmitter >
为名为 eventName 的事件添加单次的 listener 函数。 下次触发 eventName 时,将移除此监听器,然后再调用。
once方法与on方法类似,作用均为对指定事件绑定事件处理函数,区别在于,当事件处理函数执行一次后立即被结束,即该事件处理函数只会被执行一次。once方法所用参数与on方法所用参数相同。
默认情况下,事件监听器按添加顺序调用。
var http = require("http");
//创建服务器对象
var server = http.createServer();
//给服务器对象绑定多个事件处理函数
server.once('request',function(req,res){
console.log('接收到客户端请求')
})
server.on("request",function(req,res){
console.log('处理客户端请求')
console.log(req.url);
res.end();
})
server.once('request',function(req,res){
console.log('发送响应完毕')
})
//服务器启动监听
server.listen(80,function(){
console.log('http://127.0.0.1')
});
由结果可以看出,once方法绑定的事件处理函数只执行了一次。
(3)使用removeListener方法取消事件处理函数
emitter.removeListener(eventName, listener);
eventName < string > | < symbol >
listener < Function >
返回:< EventEmitter >
从名为 eventName 的事件的监听器数组中移除指定的 listener。
removeListener() 最多从监听器数组中删除一个监听器实例。 如果任何单个监听器已多次添加到指定 eventName 的监听器数组中,则必须多次调用 removeListener() 以删除每个实例。
一旦事件被触发,则所有在触发时绑定到它的监听器都会被依次调用。这意味着在触发之后和最后一个监听器完成执行之前的任何 removeListener()或removeAllListeners()调用都不会从正在进行的 emit() 中删除它们。后续事件按预期运行。
举例如下:
const event = require('events');
//创建EventEmitter的实例对象
const myEmitter = new event.EventEmitter();
const f1 = function (){
console.log('f1的结果为1');
myEmitter.removeListener('conduct',f2)
};
const f2 = function (){
console.log('f2的结果为2')
};
myEmitter.on('conduct',f1);
myEmitter.on('conduct',f2);
//手动触发事件
myEmitter.emit('conduct');
//结果为1 2,可见,虽然我们在f1里删除了f2,但它依旧被调用了
myEmitter.emit('conduct');
//结果为1,此时f2才被删除
当单个函数被多次添加为单个事件的句柄时(如下例所示),则 removeListener() 将删除最近添加的实例。如:
const event = require('events');
const myEmitter = new event.EventEmitter();
function f1(){
console.log('茕茕孑立,形影相吊');
}
function f2(){
console.log('北风卷地白草折,胡天八月即飞雪')
}
myEmitter.on('bear6',f1);
myEmitter.on('bear6',f2);
myEmitter.on('bear6',f1);
myEmitter.on('bear6',f2);
myEmitter.removeListener('bear6',f2);
myEmitter.emit('bear6');
//我们给myEmitter绑定了多个名字相同的事件,removeListener()删除最近添加的实例。
(4)自定义事件并将其触发
emitter.emit(eventName[, ...args]);
eventName < string > | < symbol >
…args < any > 自定义参数
返回: < boolean >
按注册顺序同步地调用为名为 eventName 的事件注册的每个监听器,并将提供的参数传给每个监听器。
如果事件有监听器,则返回 true,否则返回 false。
const event = require('events');
const myEmitter = new event.EventEmitter();
myEmitter.on('bear6',function first() {
console.log('这是第一个监听器');
});
myEmitter.on('bear6',function second(arg1,arg2){
console.log(`这是第二个监听器${arg1},${arg2}`);
});
myEmitter.on('bear6',function third(...args){
console.log(`这是第三个监听器${args}`);
});
myEmitter.emit('bear6',1,2,3,4,5);
结果如下:
四、错误事件
当 EventEmitter 实例中发生错误时,典型的操作是触发 ‘error’ 事件。 这些在 Node.js 中被视为特殊情况。
如果 EventEmitter 没有为 ‘error’ 事件注册至少一个监听器,并且触发 ‘error’ 事件,则会抛出错误,打印堆栈跟踪,然后退出 Node.js 进程。
为了防止 Node.js 进程崩溃,应始终为 ‘error’ 事件添加监听器。
const event = require('events');
const myEmitter = new event.EventEmitter();
myEmitter.on('error',function (err){
console.error('this is error')
});
myEmitter.emit('error');
事件处理过程中抛出的错误,可以使用try…catch捕获。
let EventEmitter = require('events').EventEmitter;
let emitter = new EventEmitter();
emitter.on('beep',function(){
console.log('beep');
});
emitter.on('beep',function(){
throw Error('oops!');
});
emitter.on('beep',function(){
console.log('beep again');
});
console.log('before emit');
try{
emitter.emit('beep');
}catch(err){
console.error('caught while emitting:',err.message);
}
console.log('after emit');
从结果中可以看出,beep again并没有被打印,因为经过try…catch…后,catch接收到了错误并抛出,beep事件错误后面的监听器不会被启动。
最后
以上就是标致外套为你收集整理的Node.js学习五(事件)一、Node.js事件循环二、事件驱动程序三、事件触发器四、错误事件的全部内容,希望文章能够帮你解决Node.js学习五(事件)一、Node.js事件循环二、事件驱动程序三、事件触发器四、错误事件所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复