事件简介
Node.js 是单进程单线程应用程序,但是因为 V8 引擎提供的异步执行回调接口,通过这些接口可以处理大量的并发,所以性能非常高。
Node.js 几乎每一个 API 都是支持回调函数的。
Node.js 基本上所有的事件机制都是用设计模式中观察者模式实现。
Node.js 单线程类似进入一个while(true)的事件循环,直到没有事件观察者退出,每个异步事件都生成一个事件观察者,如果有事件发生就调用该回调函数.
事件驱动
Node.js 使用事件驱动模型,当web server接收到请求,就把它关闭然后进行处理,然后去服务下一个web请求。当这个请求完成,它被放回处理队列,当到达队列开头,这个结果被返回给用户。这个模型非常高效可扩展性非常强,因为webserver一直接受请求而不等待任何读写操作。(这也被称之为非阻塞式IO或者事件驱动IO)
事件循环图
图片来自菜鸟教程Events模块
大多数 Node.js 核心 API 都采用惯用的异步事件驱动架构,其中某些类型的对象(触发器)会周期性地触发命名事件来调用函数对象(监听器)。
所有能触发事件的对象都是 EventEmitter
类的实例。 这些对象开放了一个 eventEmitter.on()
函数,允许将一个或多个函数绑定到会被对象触发的命名事件上。 事件名称通常是驼峰式的字符串,但也可以使用任何有效的 JavaScript 属性名。
当 EventEmitter
对象触发一个事件时,所有绑定在该事件上的函数都被同步地调用。 监听器的返回值会被丢弃。
使用events
模块
const EventEmitter = require('events')
示例代码
第一个例子,一个绑定了一个监听器的EventEmitter
实例。
const EventEmitter = require('events') // 引入事件模块
const event = new EventEmitter() // 创建实例
// 注册监听器
event.on('event', () => {
console.log('触发了一个事件!')
})
// 触发事件
event.emit('event')
// > 执行和结果
// node test_01.js
// 触发了一个事件!
关于监控器中的this
eventEmitter.emit()
方法允许将任意参数传给监听器函数。 当一个普通的监听器函数被 EventEmitter
调用时,标准的 this 关键词会被设置指向监听器所附加的 EventEmitter
。也可以使用 ES6 的箭头函数作为监听器。但是这样 this 关键词就不再指向 EventEmitter 实例。
下面通过代码理解
// 注册监听器,并接受内容
event.on('message', (message) => {
console.log('接收到的信息:' + message);
})
// 触发
event.emit('message', 'Hello world')
// 输出:接收到的信息:Hello world
// 注意
// 使用ES6的箭头函数时,this不再执行events实例。
// 做个测试
event.on('test1', function () {
console.log('this的指向:')
console.log(this)
})
event.emit('test1')
// this的指向:
// EventEmitter {
// _events:
// { event: [Function],
// message: [Function],
// test1: [Function],
// test2: [Function] },
// _eventsCount: 4,
// _maxListeners: undefined }
event.on('test2', () => {
console.log('this的指向:')
console.log(this)
})
event.emit('test2')
// this的指向:
// {}
只执行一次
多次触发事件会重复执行监听函数,使用once
代替on
,实现只监听一次。
let count = 0
event.on('add', () => {
console.log(++count)
})
event.emit('add')
// count = 1
event.emit('add')
// count = 2
let onceCount = 0
event.once('once', () => {
console.log(++onceCount) // 先 加 1 在输出
})
event.emit('once')
// 1
event.emit('once')
// 忽略
其他
- 监听器数量:默认情况下,特定事件添加超过10个监听器,就会出现警告。可以通过
setMaxListeners()
方法修改限制。 - 移除监听器:两个方法
removeListener
和removeAllListeners
。 - 监听器名称数组:getNames()
- 监听器添加和移除时,分别触发
newListener
和removeListener
事件。
说明
上面的内容只是学习时候的笔记,所有内容都可以在参考网址中找到。
示例代码已发布到Github-Node
网友评论