探索 EventEmitter 在 Node.js 中的实现

栏目: Node.js · 发布时间: 5年前

内容简介:你有没有想过,为什么浏览器的 div 上可以绑定多个实际上这一切都是 EventEmitter 在背后做支持,它是 JavaScript 经典的事件驱动实现,现在我们来看下 Node.js 中是如何实现的。本文所说的监听事件在实现上都为函数,读者可以认为两者相等以方便阅读。
探索 EventEmitter 在 Node.js 中的实现

你有没有想过,为什么浏览器的 div 上可以绑定多个 onclick 事件,点击一下 div 可以触发全部的事件,jquery 的 .on().off()one() 又是如何实现的?Node.js 事件驱动的原理是怎样的?

实际上这一切都是 EventEmitter 在背后做支持,它是 JavaScript 经典的事件驱动实现,现在我们来看下 Node.js 中是如何实现的。

本文所说的监听事件在实现上都为函数,读者可以认为两者相等以方便阅读。

因为原来的 Node 代码量比较多,为了方便演示,作者把本文的源代码示例中涉及数据验证,错误处理的部分删除,保留了主要内容。

准备:

概览 EventEmitter

内部属性:

_events
_eventsCount

主要方法:

emitter.addListener/on(eventName, listener)
emitter.prependListener(eventName, listener)
emitter.emit(eventName[, ...args])
emitter.removeListener/off(eventName, listener)
emitter.once(eventName, listener)
emitter.removeAllListeners([eventName])

正文

1. 初始化 init

探索 EventEmitter 在 Node.js 中的实现

_events 不存在时,使用 Object.create(null) 来初始化,并把 _eventsCount 设 0。

划重点 —— Object.create(null) 可以创建一个没有原型的对象。

为什么要用这种方法创建对象呢?开发者这么做的目的其实还是出于性能上的考虑,因为 EventEmitter 在 Node.js 中应用广泛,为节省服务器内存和执行速度上不必要的开销,肯定能省则省呗。

2. 添加事件绑定 addListener

探索 EventEmitter 在 Node.js 中的实现

首先判断 target_events 是否存在,如果不存在则还是用 Object.create(null) 创建。

如果存在,触发 newListener 类型的事件。然后通过 event[type] 找到已经注册 type 类型的监听事件/监听事件数组,并存到 existing 中。

如果该事件值为 undefined ,则把直接把要注册的监听事件 listener 赋给不存在的事件。否则,更新事件数组(单一的 listener 要转为数组)。

注意 prepend 的使用,可以灵活地把 listener 添加到监听函数数组头部或尾部。

3. 事件添加到数组头部 prependListener

探索 EventEmitter 在 Node.js 中的实现
和 addListener 类似,但是 prependtrue

2. 触发事件 emit

探索 EventEmitter 在 Node.js 中的实现

若 handler 不存在,直接返回 false。

若 handler 是一个函数,使用 Reflect 调用函数。如果是数组的话则遍历数组并调用,然后返回 true。

3 移除事件绑定 removeListener

探索 EventEmitter 在 Node.js 中的实现

type 取出要删除的监听函数列表 list = event[type] ,当 list 等于要删除的监听函数时, _eventsCount 减一后如果为 0,直接初始化 _events ,否则只删除当前类型的监听函数。

接着往下看,若 typeof list !== 'function'list 为数组时,先确定要删除监听事件的位置 position ,然后删掉对应的函数。

注意:为什么不用 list.splice(postion, 1) 而要专门写一个 spliceOne 来删除呢?

探索 EventEmitter 在 Node.js 中的实现

因为这个两参数的方法要比内置的 splice 可能快上 1.5 - 10 倍 !我专门查看了下提交记录,这个版本的方法经过几个开发者改动过最终成为现在这个样子。不得不佩服各路大神对开源的贡献!至于 splice 为什么慢,我没能查到原因,也许需要去看 v8 源码。

4 事件只能执行一次 once

探索 EventEmitter 在 Node.js 中的实现

这个方法比较简单,主要能理解 onceWrapper 方法就行。

其它还有一些方法,我不再多写了,基本上原理就是这样。有兴趣的同学可以自己点击前文的源码链接查看。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

用户体验草图设计

用户体验草图设计

比尔·巴克斯顿(Bill Buxton) / 黄峰 / 电子工业出版社 / 2009-11 / 168.00元

《用户体验草图设计:正确地设计,设计得正确(全彩)》:比尔·盖茨亲笔推荐版 人因国际、百度、华为、微软、腾讯用户体验部门联合推荐!一起来看看 《用户体验草图设计》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

URL 编码/解码
URL 编码/解码

URL 编码/解码