接前面
- JavaScript基础学习:ECMAScript 基础知识
- Node.js学习笔记(一):Node.js是什么,如何安装,如何简单使用,工作目录与脚本所在目录获取
- Node.js学习笔记(二):命令行参数、环境变量、标准输入、标准输出、标准出错、信号处理、程序返回值,打包
- Node.js学习笔记(三):fs模块API,三种风格——同步、异步回调、异步promise,三种层级——底层、高层、流
- Node.js学习笔记(四):网络功能:tcp、udp、tls、http、...
- Node.js学习笔记(五):事件模块:EventEmitter、Event、EventTarget、NodeEventTarget
继续了解Node.js。看看events模块
引言
Nodejs手册中介绍说:
Node.js核心API的很大一部分是基于一种惯用的异步事件驱动架构构建的,其中某些类型的对象(称为“emitters”)会发出命名事件,从而调用函数对象(“listeners”)。
功能类似的三个类:
- EventEmitter,Nodejs中事件发射类
- EventTarget,Nodejs中仿WebAPI接口类
- NodeEventTarget,Nodejs将EventTarget封装成类似EventEmitter的接口
EventEmitter
事件模块的核心类是 EventEmitter,我觉得可以先和Qt信号槽对比一下:
特性/概念 | EventEmitter (Node.js) |
QObject (Qt) |
---|---|---|
模块 | 内置模块 (events ) |
核心库( QtCore ) |
实例化 | const emitter = new EventEmitter(); |
QObject 的派生类的实例化 |
添加监听器 | on() 或 addListener() |
connect() |
发射 | emit() |
调用信号函数,一个空的 emit宏 |
一次性监听 | once() |
connect() 使用Qt::UniqueConnection |
移除监听器 | off() 、removeListener() 或 removeAllListeners() |
disconnect() |
传递参数 | 通过 emit 方法传递参数给监听器 |
通过信号的参数列表传递数据给槽函数 |
自定义事件 | 灵活 | 派生QObject 增加信号 |
通过on()
来添加事件监听器,我们在标准输入处理,文件系统模块fs,各种网络模块中的例子中都已经反复在用了。但是只是照猫画虎,需要稍微多了解一点点。
不妨,通过若干简短的例子来学习一下
初识 EventEmitter
建立自定义事件(mySignal)和监听器的连接,而后 emit自定义事件:
1 2 3 4 5 6 7 8 9 10 11 |
|
可以多次emit,以多次触发监听器:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
如果多次emit,只想响应一次,只需要使用once()
而不是on()
:
1 2 3 4 5 6 7 8 9 10 11 12 |
|
如果多次建立连接,回调会被调用同样次数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
传递参数
传递参数简单,直接就是函数参数:
1 2 3 4 5 6 7 8 9 10 11 |
|
如果要使用 this的话,注意不要用箭头函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
EventTarget 与 Event
Nodejs提供了仿WebAPI中的EventTarget,Event、CustomEvent。EventTarget不是EventEmitter派生类,接口简单:
- eventTarget.addEventListener()
- eventTarget.dispatchEvent()
- eventTarget.removeEventListener()
Node.js 的 EventTarget与Web API的EventTarget 有所不同:
- 在 Node.js 中,没有层次结构或事件传播的概念。分发到
EventTarget
的事件不会自动在嵌套的目标对象层次结构中传播。每个EventTarget
独立处理其自己的处理程序集。 - 在 Node.js 中,如果事件监听器是异步函数或返回
Promise
,并且该Promise
被拒绝,拒绝将自动捕获并与同步抛出的监听器一样处理。
例子
简单例子:
1 2 3 4 5 6 7 |
|
输出结果:
1 2 3 4 5 6 7 |
|
要传递参数的话,用CustomEvent而不是Event
1 2 3 4 5 6 7 8 9 10 11 |
|
所谓CustomEvent,也是标准定义好的。提供了detail成员。
NodeEventTarget
nodejs从EventTarget派生出 NodeEventTarget,以模仿EventEmitter的接口。
但是奇怪,文档少的可怜,我连一个小的demo都凑不齐(跑不通)
1 2 3 4 5 6 7 8 9 10 11 |
|
查看源码,发现其在文件 lib/internal/event_target.js内:
1 2 3 4 5 6 7 8 9 |
|
还是不知道怎么用,以后慢慢看...
参考
- https://nodejs.org/api/events.html
- https://dom.spec.whatwg.org/#event