探索 EventEmitter 在 Node.js 中的实现

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

内容简介:你有没有想过,为什么浏览器的 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 方法就行。

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


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

查看所有标签

猜你喜欢:

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

精通Java并发编程(第2版)

精通Java并发编程(第2版)

[西] 哈维尔·费尔南德斯·冈萨雷斯 / 唐富年 / 人民邮电出版社 / 2018-10 / 89.00元

Java 提供了一套非常强大的并发API,可以轻松实现任何类型的并发应用程序。本书讲述Java 并发API 最重要的元素,包括执行器框架、Phaser 类、Fork/Join 框架、流API、并发数据结构、同步机制,并展示如何在实际开发中使用它们。此外,本书还介绍了设计并发应用程序的方法论、设计模式、实现良好并发应用程序的提示和技巧、测试并发应用程序的工具和方法,以及如何使用面向Java 虚拟机的......一起来看看 《精通Java并发编程(第2版)》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具