核心模块之Events
通过EventEmitter类实现事件统一管理
events与EventEmitter
- node.js是基于事件驱动的异步操作架构,内置events模块
- events模块提供了EventEmitter类
- node.js中很多内置核心模块集成EventEmitter
EventEmitter常见Api
- on
- 添加实现被触发时调用的回调函数
const EventEmitter = require('events')
const ev = new EventEmitter()
// on
ev.on('事件1', () => {
console.log('事件1执行了---2')
})
ev.on('事件1', () => {
console.log('事件1执行了')
})
- emit
- 出发事件,按照注册的顺序同步调用每个事件监听器
// emit触发
ev.emit('事件1')
- once
- 添加当事件在注册之后首次被触发时调用的回调函数
ev.once('事件1', () => {
console.log('事件1执行了')
})
ev.once('事件1', () => {
console.log('事件1执行了--2')
})
ev.emit('事件1')
ev.emit('事件1')
- off
- 移除特定的监听器
let cbFn = (...args) => {
console.log(args)
}
ev.on('事件1', cbFn)
ev.emit('事件1')
// 移除
ev.off('事件1', cbFn)
ev.emit('事件1', 1, 2, 3)
发布订阅
- 缓存队列,存放订阅者消息
- 具有增加和删除订阅的能力
- 状态改变时通知所有订阅者执行监听
- 发布订阅存在一个调度中心,而观察者中是不存在的
- 状态发生改变时,发布订阅无须主动通知订阅者
class PubSub{
constructor() {
this._events = {}
}
// 注册
subscribe(event, callback) {
if (this._events[event]) {
// 如果当前 event 存在,所以我们只需要往后添加当前次监听操作
this._events[event].push(callback)
} else {
// 之前没有订阅过此事件
this._events[event] = [callback]
}
}
// 发布
publish(event, ...args) {
const items = this._events[event]
if (items && items.length) {
items.forEach(function (callback) {
callback.call(this, ...args)
})
}
}
}
let ps = new PubSub()
ps.subscribe('事件1', () => {
console.log('事件1执行了')
})
ps.subscribe('事件1', () => {
console.log('事件1执行了---2')
})
ps.publish('事件1')
ps.publish('事件1')
EventEmitter模拟
function MyEvent () {
// 准备一个数据结构用于缓存订阅者信息
this._events = Object.create(null)
}
MyEvent.prototype.on = function (type, callback) {
// 判断当前次的事件是否已经存在,然后再决定如何做缓存
if (this._events[type]) {
this._events[type].push(callback)
} else {
this._events[type] = [callback]
}
}
MyEvent.prototype.emit = function (type, ...args) {
if (this._events && this._events[type].length) {
this._events[type].forEach((callback) => {
callback.call(this, ...args)
})
}
}
MyEvent.prototype.off = function (type, callback) {
// 判断当前 type 事件监听是否存在,如果存在则取消指定的监听
if (this._events && this._events[type]) {
this._events[type] = this._events[type].filter((item) => {
return item !== callback && item.link !== callback
})
}
}
MyEvent.prototype.once = function (type, callback) {
let foo = function (...args) {
callback.call(this, ...args)
this.off(type, foo)
}
foo.link = callback
this.on(type, foo)
}
let ev = new MyEvent()
let fn = function (...data) {
console.log('事件1执行了', data)
}
ev.once('事件1', fn)
// ev.off('事件1', fn)
ev.emit('事件1', '前')