We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
我们了解到,Node 采用了事件驱动机制,而EventEmitter 就是Node实现事件驱动的基础
Node
EventEmitter
在EventEmitter的基础上,Node 几乎所有的模块都继承了这个类,这些模块拥有了自己的事件,可以绑定/触发监听器,实现了异步操作
Node.js 里面的许多对象都会分发事件,比如 fs.readStream 对象会在文件被打开的时候触发一个事件
Node.js
这些产生事件的对象都是 events.EventEmitter 的实例,这些对象有一个 eventEmitter.on() 函数,用于将一个或多个函数绑定到命名事件上
Node 的events模块只提供了一个EventEmitter类,这个类实现了Node异步事件驱动架构的基本模式——观察者模式
events
在这种模式中,被观察者(主体)维护着一组其他对象派来(注册)的观察者,有新的对象对主体感兴趣就注册观察者,不感兴趣就取消订阅,主体有更新的话就依次通知观察者们
基本代码如下所示:
const EventEmitter = require('events') class MyEmitter extends EventEmitter {} const myEmitter = new MyEmitter() function callback() { console.log('触发了event事件!') } myEmitter.on('event', callback) myEmitter.emit('event') myEmitter.removeListener('event', callback);
通过实例对象的on方法注册一个名为event的事件,通过emit方法触发该事件,而removeListener用于取消事件的监听
on
event
emit
removeListener
关于其常见的方法如下:
通过上面的方法了解,EventEmitter是一个构造函数,内部存在一个包含所有事件的对象
class EventEmitter { constructor() { this.events = {}; } }
其中events存放的监听事件的函数的结构如下:
{ "event1": [f1,f2,f3], "event2": [f4,f5], ... }
然后开始一步步实现实例方法,首先是emit,第一个参数为事件的类型,第二个参数开始为触发事件函数的参数,实现如下:
emit(type, ...args) { this.events[type].forEach((item) => { Reflect.apply(item, this, args); }); }
当实现了emit方法之后,然后实现on、addListener、prependListener这三个实例方法,都是添加事件监听触发函数,实现也是大同小异
addListener
prependListener
on(type, handler) { if (!this.events[type]) { this.events[type] = []; } this.events[type].push(handler); } addListener(type,handler){ this.on(type,handler) } prependListener(type, handler) { if (!this.events[type]) { this.events[type] = []; } this.events[type].unshift(handler); }
紧接着就是实现事件监听的方法removeListener/on
removeListener/on
removeListener(type, handler) { if (!this.events[type]) { return; } this.events[type] = this.events[type].filter(item => item !== handler); } off(type,handler){ this.removeListener(type,handler) }
最后再来实现once方法, 再传入事件监听处理函数的时候进行封装,利用闭包的特性维护当前状态,通过fired属性值判断事件函数是否执行过
once
fired
once(type, handler) { this.on(type, this._onceWrap(type, handler, this)); } _onceWrap(type, handler, target) { const state = { fired: false, handler, type , target}; const wrapFn = this._onceWrapper.bind(state); state.wrapFn = wrapFn; return wrapFn; } _onceWrapper(...args) { if (!this.fired) { this.fired = true; Reflect.apply(this.handler, this.target, args); this.target.off(this.type, this.wrapFn); } }
完整代码如下:
class EventEmitter { constructor() { this.events = {}; } on(type, handler) { if (!this.events[type]) { this.events[type] = []; } this.events[type].push(handler); } addListener(type,handler){ this.on(type,handler) } prependListener(type, handler) { if (!this.events[type]) { this.events[type] = []; } this.events[type].unshift(handler); } removeListener(type, handler) { if (!this.events[type]) { return; } this.events[type] = this.events[type].filter(item => item !== handler); } off(type,handler){ this.removeListener(type,handler) } emit(type, ...args) { this.events[type].forEach((item) => { Reflect.apply(item, this, args); }); } once(type, handler) { this.on(type, this._onceWrap(type, handler, this)); } _onceWrap(type, handler, target) { const state = { fired: false, handler, type , target}; const wrapFn = this._onceWrapper.bind(state); state.wrapFn = wrapFn; return wrapFn; } _onceWrapper(...args) { if (!this.fired) { this.fired = true; Reflect.apply(this.handler, this.target, args); this.target.off(this.type, this.wrapFn); } } }
测试代码如下:
const ee = new EventEmitter();// 注册所有事件ee.once('wakeUp', (name) => { console.log(`${name} 1`); });ee.on('eat', (name) => { console.log(`${name} 2`) });ee.on('eat', (name) => { console.log(`${name} 3`) });const meetingFn = (name) => { console.log(`${name} 4`) };ee.on('work', meetingFn);ee.on('work', (name) => { console.log(`${name} 5`) });ee.emit('wakeUp', 'xx');ee.emit('wakeUp', 'xx'); // 第二次没有触发ee.emit('eat', 'xx');ee.emit('work', 'xx');ee.off('work', meetingFn); // 移除事件ee.emit('work', 'xx'); // 再次工作
The text was updated successfully, but these errors were encountered:
上面的实现无法通过下面的测试用例:
const ee = new EventEmitter(); const aa = (name) => { console.log(`${name} 1`); } ee.once('wakeUp', aa); ee.off('wakeUp', aa); ee.emit('wakeUp', 'xx');
Sorry, something went wrong.
No branches or pull requests
一、是什么
我们了解到,
Node
采用了事件驱动机制,而EventEmitter
就是Node
实现事件驱动的基础在
EventEmitter
的基础上,Node
几乎所有的模块都继承了这个类,这些模块拥有了自己的事件,可以绑定/触发监听器,实现了异步操作Node.js
里面的许多对象都会分发事件,比如 fs.readStream 对象会在文件被打开的时候触发一个事件这些产生事件的对象都是 events.EventEmitter 的实例,这些对象有一个 eventEmitter.on() 函数,用于将一个或多个函数绑定到命名事件上
二、使用方法
Node
的events
模块只提供了一个EventEmitter
类,这个类实现了Node
异步事件驱动架构的基本模式——观察者模式在这种模式中,被观察者(主体)维护着一组其他对象派来(注册)的观察者,有新的对象对主体感兴趣就注册观察者,不感兴趣就取消订阅,主体有更新的话就依次通知观察者们
基本代码如下所示:
通过实例对象的
on
方法注册一个名为event
的事件,通过emit
方法触发该事件,而removeListener
用于取消事件的监听关于其常见的方法如下:
三、实现过程
通过上面的方法了解,
EventEmitter
是一个构造函数,内部存在一个包含所有事件的对象其中
events
存放的监听事件的函数的结构如下:然后开始一步步实现实例方法,首先是
emit
,第一个参数为事件的类型,第二个参数开始为触发事件函数的参数,实现如下:当实现了
emit
方法之后,然后实现on
、addListener
、prependListener
这三个实例方法,都是添加事件监听触发函数,实现也是大同小异紧接着就是实现事件监听的方法
removeListener/on
最后再来实现
once
方法, 再传入事件监听处理函数的时候进行封装,利用闭包的特性维护当前状态,通过fired
属性值判断事件函数是否执行过完整代码如下:
测试代码如下:
参考文献
The text was updated successfully, but these errors were encountered: