首页 > 语言 > JavaScript > 正文

详解如何模拟实现node中的Events模块(通俗易懂版)

2024-05-06 15:40:42
字体:
来源:转载
供稿:网友

Nodejs 的大部分核心 API 都是基于异步事件驱动设计的,事件驱动核心是通过 node 中 Events 对象来实现事件的发送和监听回调绑定,我们常用的 stream 模块也是依赖于 Events 模块是来实现数据流之间的回调通知,如在数据到来时触发 data 事件,流对象为可读状态触发 readable 事件,当数据读写完毕后发送 end 事件。

既然 Events 模块如此重要,我们有必要来学习一下 Events 模块的基本使用,以及如何模拟实现 Events 模块中常用的 api

一、Events 模块的基本使用以及简单实现

首先我们了解一下 Events 模块的基本用法,其实 Events 模块本质上是观察者模式的实现,所谓观察者模式就是:

它定义了对象间的一种一对多的关系,让多个观察者对象同时监听某一个主题对象,当一个对象发生改变时,所有依赖于它的对象都将得到通知

观察者模式有对应的观察者以及被观察的对象,在 Events 模块中,对应的实现就是 on 和 emit 函数

const EventEmitter = require('events');class MyEmitter extends EventEmitter {}const myEmitter = new MyEmitter();myEmitter.on('嗨', (str) => { console.log(str);});myEmitter.emit('嗨','你好');

从上述的使用中,我们可以知道 on 是用来监听事件的发生,而 emit 是用来触发事件的发生,一旦 emit 触发了事件,on 就会被通知到,从而执行对应的回调函数。

有了这个实例,我们可以思考下如何实现这个 EventEmitter 类。

思路:当我们执行 on 函数时,我们可以将回调函数保存起来,等到 emit 触发了事件时,将回调函数拿出来执行,那么就可以实现了事件的监听以及订阅了。

class EventEmitter{ constructor(){  #事件监听函数保存的地方  this.events={}; } on(eventName,listener){  if (this.events[eventName]) {   this.events[eventName].push(listener);  } else {   #如果没有保存过,将回调函数保存为数组   this.events[eventName] = [listener];  } } emit(eventName){  #emit触发事件,把回调函数拉出来执行  this.events[eventName] && this.events[eventName].forEach(listener => listener()) }}

上述就实现了一个简单的 EventEmitter 类,下面来实例一下:

let event = new EventEmitter();event.on('嗨',function(){ console.log('你好');});event.emit('嗨');#输出:你好

完善:我们注意到在原生的 EventEmitter 类中,emit 是可以传递参数到我们的回调函数中,那么我们实现的类也应该支持传递参数。我们对 emit 进行如下更改

emit(eventName,...rest){ #emit触发事件,把回调函数拉出来执行 this.events[eventName] && this.events[eventName].forEach(listener => listener.apply(this,rest))}            
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选