探索 EventEmitter 在 Node.js 中的实现

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

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

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


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

查看所有标签

猜你喜欢:

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

深入浅出 MFC 第二版

深入浅出 MFC 第二版

侯俊杰 / 松岗 / 1997.05

深入浅出MFC是一本介绍 MFC(Microsoft Foundation Classes)程式设计技术的书籍。对於 Windows 应用软体的开发感到兴趣,并欲使用 Visual C++ 整合环境的视觉开发工具,以 MFC 为程式基础的人,都可以从此书获得最根本最重要的知识与实例。 如果你是一位对 Application Framework 和物件导向(Object Orien......一起来看看 《深入浅出 MFC 第二版》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具