events (事件)

1,530 阅读2分钟

所有能触发事件的对象都是 EventEmitter 类的实例。 这些对象开放了一个 eventEmitter.on() 函数,允许将一个或多个函数绑定到会被对象触发的命名事件上。 事件名称通常是驼峰式的字符串,但也可以使用任何有效的 JavaScript 属性名。

EventEmitter 对象触发一个事件时,所有绑定在该事件上的函数都被同步地调用。 监听器的返回值会被丢弃。

on与once

on与once都用于注册监听器,区别是on的回调方法在每一次监听事件emitter时都会被触发;而once监听的事件一旦被触发,这个事件once对应的监听器便会被注销。

     

import { EventEmitter } from 'events';

const emitter = new EventEmitter();
    // 只处理一次,不会无限循环
    emitter.once('timePass', () => {
      console.log('once注册监听的事件被触发了');
     });
    emitter.on('time', () => {
       console.log('on注册监听的事件被触发了');
    });
    emitter.emit('timePass');
    emitter.emit('time');
    setTimeout(() => {
       emitter.emit('timePass');
       emitter.emit('time');
    }, 3000);

打印结果

once注册监听的事件被触发了
on注册监听的事件被触发了
on注册监听的事件被触发了 

emitter.setMaxListeners(n)

默认情况下,一个事件所拥有的监听器数量是固定的,一旦监听器数量过多,EventEmitter会打印一个警告,这样有助内存泄露时定位问题。事件所能拥有的监听器数量可以通过

setMaxListeners进行设置。值设为 Infinity(或 0)表明不限制监听器的数量。

emitter.removeListener(eventName, listener)

  • 注销指定名称的监听器。如果一个事件被多次注册相同eventName的监听器,则必须多次调用 removeListener 才能移除每个实例。
  • 一个监听器一旦被触发,则其所对应的监听器回调一定会被触发。除非removeListener在emitter之前执行。

const eventCb = function() {
  console.log('time的监听事件的回调');
}; 
emitter.on('time', eventCb);
emitter.removeListener('time', eventCb);
emitter.emit('time');
>> 不会有log被打印出来

改变removeListener与emit执行顺序:

const eventCb = function() {
  console.log('time的监听事件的回调');
};    
    emitter.on('time', eventCb);
    emitter.on('time', eventCb);
    emitter.emit('time');
    emitter.removeListener('time', eventCb); 

>> time的监听事件的回调
   time的监听事件的回调
  • removeListener的回调与其对应的监听器的回调必须是同一个实例,否则removeListener不生效

错误写法,这样removeListener的永远不会被成功执行

    emitter.on('time', () => { console.log('dsf')});
    emitter.emit('time');
    emitter.removeListener('time', () => { console.log('dsf')}); 

正确写法:

    const eventCb = function() {  console.log('time的监听事件的回调');};
    emitter.on('time', eventCb);
    emitter.emit('time');
    emitter.removeListener('time', eventCb);