Skip to content

Latest commit

 

History

History
138 lines (103 loc) · 3.64 KB

03-事件.md

File metadata and controls

138 lines (103 loc) · 3.64 KB

事件

本节解决上一节遗留的第一个问题 —— “req.on这里的on是特定的吗?”

req.on('data', function (chunk) {

})
req.on('end', function () {

})

以上代码的格式其实应该比较熟悉的,和前端用 jQuery 绑定事件类似

$('#btn1').on('click', function (event) {

})

这两点能对应起来,就好说了。


目录

  • 观察者模式
  • EventEmitter 基本使用
  • EventEmitter 继承
  • 总结

观察者模式

作为程序猿多少要了解 23 种设计模式,其中观察者模式是非常重要的一个。简单说来,就是定义好监听的操作,然后等待事件的触发。前端开发中,有不少地方能体现观察者模式。最简单的例如绑定事件:

$('#btn1').on('click', function (event) {
    alert(1)
})
$('#btn1').on('click', function (event) {
    alert(2)
})

比较复杂的例如 vue 中,修改data之后,会立刻出发视图重新渲染,这也是观察者模式的应用。


EventEmitter 基本使用

nodejs 中的自定义事件也是观察者模式的一种体现,而且自定义事件常见于 nodejs 的各个地方。先看一个简单示例

const EventEmitter = require('events').EventEmitter

const emitter1 = new EventEmitter()
emitter1.on('some', () => {
    // 监听 some 事件
    console.log('some event is occured 1')
})
emitter1.on('some', () => {
    // 监听 some 事件
    console.log('some event is occured 2')
})
// 触发 some 事件
emitter1.emit('some')

以上代码中,先引入 nodejs 提供的EventEmitter构造函数,然后初始化一个实例emitter1。实例通过on可监听事件,emit可以触发事件,事件名称可以自定义,如some

自定义事件触发的时候还可传递参数,例如

const emitter = new EventEmitter()
emitter.on('sbowName', name => {
    console.log('event occured ', name)
})
emitter.emit('sbowName', 'zhangsan')  // emit 时候可以传递参数过去

还有自定义事件的异常捕获,如下形式:

// 例四
const emitter1 = new EventEmitter()
emitter1.on('some', () => {
    console.log('11111')
})
emitter1.on('some', () => {
    console.log('22222')
    throw new Error('自定义错误') // 触发过程中抛出错误
})
emitter1.on('some', () => {
    console.log('33333')
})
try {
    emitter1.emit('some')
} catch (ex) {
    console.log(ex.stack)  // 可以捕获到事件执行过程中的错误
}
console.log('after emit')

再次回顾上一节的req.on('data' ...req.on('end', ...,和这里是一样的,就是监听dataend两个事件。但是,上文是EventEmitter实例才有这样的功能,req并没有看到是EventEmitter的实例 —— 下文解惑。


EventEmitter 继承

上文说到EventEmitter实例有onemit接口,其实自定义 class 的实例也可以有,只不过需要继承EventEmitter。使用 ES6 的继承语法很容易实现

// 任何构造函数都可以继承 EventEmitter 的方法 on emit
class Dog extends EventEmitter {
    constructor(name) {
        super()
        this.name = name
    }
}
var simon = new Dog('simon')
simon.on('bark', function () {
    console.log(this.name, ' barked')
})
setInterval(() => {
    simon.emit('bark')
}, 500)

这么说,req.on('data' ...req.on('end', ...中,其实req的构造函数已经继承了EventEmitter,因此req才会有on接口。


总结

本节介绍了EventEmitter的使用,并顺带解释了req.on('data' ...req.on('end', ...中的on。以后只要看到xxx.on()xxx.emit(),就应该想到这里的自定义事件。