NodeJS Events 必知必会

1. 环境

  • node 8.11.3

2. 基础运用

// 01.js

const EventEmitter = require('events');

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
  console.log('an event occurred!');
});
myEmitter.emit('event');

输出:

an event occurred!

3. 传介入this指向

  • emit()要领可以传不限定数目的参数。
  • 除了箭头函数外,在回调函数内部,this会被绑定到EventEmitter类的实例上
// 02.js
const EventEmitter = require('events')

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter()

myEmitter.on('event', function (a, b){
  console.log(a, b, this, this === myEmitter)
})

myEmitter.on('event', (a, b) => {
  console.log(a, b, this, this === myEmitter)
})

myEmitter.emit('event', 'a', {name:'wdd'})

输出:

a { name: 'wdd' } MyEmitter {
  domain: null,
  _events: { event: [ [Function], [Function] ] },
  _eventsCount: 1,
  _maxListeners: undefined } true
a { name: 'wdd' } {} false

4. 同步照样异步挪用listeners?

  • emit()法会同步根据事宜注册的递次实行回调
// 03.js
const EventEmitter = require('events')

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter()

myEmitter.on('event', () => {
  console.log('01 an event occurred!')
})

myEmitter.on('event', () => {
  console.log('02 an event occurred!')
})

console.log(1)
myEmitter.emit('event')
console.log(2)

输出:

1
01 an event occurred!
02 an event occurred!
2

深切思索,为何事宜回调要同步?异步了会有什么题目?

同步去挪用事宜监听者,可以确保根据注册递次去挪用事宜监听者,而且防止竞态前提和逻辑毛病。

5. 怎样只定阅一次事宜?

  • 运用once去只定阅一次事宜
// 04.js
const EventEmitter = require('events')

class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()

let m = 0
myEmitter.once('event', () => {
  console.log(++m)
})
myEmitter.emit('event')
myEmitter.emit('event')

6. 不定阅,就发飙的毛病事宜

error是一个迥殊的事宜名,当这个事宜被触发时,假如没有对应的事宜监听者,则会致使顺序崩溃。

events.js:183
      throw er; // Unhandled 'error' event
      ^

Error: test
    at Object.<anonymous> (/Users/xxx/github/node-note/events/05.js:12:25)
    at Module._compile (module.js:635:30)
    at Object.Module._extensions..js (module.js:646:10)
    at Module.load (module.js:554:32)
    at tryModuleLoad (module.js:497:12)
    at Function.Module._load (module.js:489:3)
    at Function.Module.runMain (module.js:676:10)
    at startup (bootstrap_node.js:187:16)
    at bootstrap_node.js:608:3

所以,最好老是给EventEmitter实例增加一个error的监听器

const EventEmitter = require('events')

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter()

myEmitter.on('error', (err) => {
  console.log(err)
})

console.log(1)
myEmitter.emit('error', new Error('test'))
console.log(2)

7. 内部事宜 newListener与removeListener

newListener与removeListener是EventEmitter实例的自带的事宜,你最好不要运用一样的名字作为自定义的事宜名。

  • newListener在定阅者被加入到定阅列表前触发
  • removeListener在定阅者被移除定阅列表后触发
// 06.js 
const EventEmitter = require('events')

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter()

myEmitter.on('newListener', (event, listener) => {
  console.log('----')
  console.log(event)
  console.log(listener)
})

myEmitter.on('myEmitter', (err) => {
  console.log(err)
})

输出:

从输出可以看出,纵然没有去触发myEmitter事宜,on()要领也会触发newListener事宜。

----
myEmitter
[Function]

8. 事宜监听数目限定

  • myEmitter.listenerCount(‘event’): 用来盘算一个实例上某个事宜的监听者数目
  • EventEmitter.defaultMaxListeners: EventEmitter类默许的最大监听者的数目,默许是10。凌驾会有正告输出。
  • myEmitter.getMaxListeners(): EventEmitter实例默许的某个事宜最大监听者的数目,默许是10。凌驾会有正告输出。
  • myEmitter.eventNames(): 返回一个实例上又若干种事宜

EventEmitter和EventEmitter实例的最大监听数目为10并非一个硬性规定,只是一个推荐值,该值可以经由过程setMaxListeners()接口去转变。

  • 转变EventEmitter的最大监听数目会影响到一切EventEmitter实例
  • 该变EventEmitter实例的最大监听数目只会影响到实例本身

如无必要,最好的不要去转变默许的监听数目限定。事宜监听数目是node检测内存泄漏的一个规范一个维度。

EventEmitter实例的最大监听数目不是一个实例的一切监听数目。

比方同一个实例A范例事宜5个监听者,B范例事宜6个监听者,这个并不会有告警。假如A范例有11个监听者,就会有告警提醒。

假如在事宜中发明相似的告警提醒Possible EventEmitter memory leak detected,要知道从事宜最大监听数的角度去排查题目。

// 07.js
const EventEmitter = require('events')

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter()

const maxListeners = 11

for (let i = 0; i < maxListeners; i++) {
  myEmitter.on('event', (err) => {
    console.log(err, 1)
  })
}

myEmitter.on('event1', (err) => {
  console.log(err, 11)
})

console.log(myEmitter.listenerCount('event'))
console.log(EventEmitter.defaultMaxListeners)
console.log(myEmitter.getMaxListeners())
console.log(myEmitter.eventNames())

输出:

11
10
10
[ 'event', 'event1' ]
(node:23957) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 event listeners added. Use emitter.setMaxListeners() to increase limit
    原文作者:Carl
    原文地址: https://segmentfault.com/a/1190000016206410
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞