Node.js v11.15.0 Documentation


Events#

Node.js核心API的大部分都基于惯用的异步事件驱动的体系结构,在该体系结构中,某些类型的对象(称为"发射器")发出命名事件,这些事件导致调用Function对象("侦听器").

例如: net.Server对象每次同级连接到它时net.Server发出一个事件; 打开文件时, fs.ReadStream发出事件; 只要有数据可供读取, 流就发出一个事件.

所有发出事件的对象都是EventEmitter类的实例. 这些对象公开了eventEmitter.on()函数,该函数允许将一个或多个函数附加到该对象发出的命名事件. 通常,事件名称是驼峰式的字符串,但是可以使用任何有效的JavaScript属性键.

EventEmitter对象发出事件时,与该特定事件相关的所有函数都被同步调用. 被调用的侦听器返回的任何值都将被忽略 ,并将被丢弃.

以下示例显示了具有单个侦听器的简单EventEmitter实例. eventEmitter.on()方法用于注册侦听器,而eventEmitter.emit()方法用于触发事件.

const EventEmitter = require('events');

class MyEmitter extends EventEmitter {}

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

Passing arguments and this to listeners#

eventEmitter.emit()方法允许将任意一组参数传递给侦听器函数. 重要的是要记住,当调用普通的侦听器函数时,有意将标准this关键字设置为引用侦听器所附加的EventEmitter实例.

const myEmitter = new MyEmitter();
myEmitter.on('event', function(a, b) {
  console.log(a, b, this, this === myEmitter);
  // Prints:
  //   a b MyEmitter {
  //     domain: null,
  //     _events: { event: [Function] },
  //     _eventsCount: 1,
  //     _maxListeners: undefined } true
});
myEmitter.emit('event', 'a', 'b');

可以将ES6箭头函数用作侦听器,但是,这样做时, this关键字将不再引用EventEmitter实例:

const myEmitter = new MyEmitter();
myEmitter.on('event', (a, b) => {
  console.log(a, b, this);
  // Prints: a b {}
});
myEmitter.emit('event', 'a', 'b');

Asynchronous vs. Synchronous#

EventEmitter以注册的顺序同步调用所有侦听器. 这对于确保事件的正确排序并避免争用条件或逻辑错误很重要. 适当时,侦听器函数可以使用setImmediate()process.nextTick()方法切换到异步操作模式:

const myEmitter = new MyEmitter();
myEmitter.on('event', (a, b) => {
  setImmediate(() => {
    console.log('this happens asynchronously');
  });
});
myEmitter.emit('event', 'a', 'b');

Handling events only once#

使用eventEmitter.on()方法注册侦听器时, 每次发出命名事件都会调用该侦听器.

const myEmitter = new MyEmitter();
let m = 0;
myEmitter.on('event', () => {
  console.log(++m);
});
myEmitter.emit('event');
// Prints: 1
myEmitter.emit('event');
// Prints: 2

使用eventEmitter.once()方法,可以注册针对特定事件最多被调用一次的侦听器. 发出事件后,将取消注册侦听器, 然后调用该侦听器.

const myEmitter = new MyEmitter();
let m = 0;
myEmitter.once('event', () => {
  console.log(++m);
});
myEmitter.emit('event');
// Prints: 1
myEmitter.emit('event');
// Ignored

Error events#

EventEmitter实例中发生错误时,典型的操作是发出'error'事件. 这些在Node.js中被视为特殊情况.

如果EventEmitter 具有用于登记至少一个收听'error'事件,以及'error'事件被发射时,该错误被抛出,堆栈跟踪被印刷,并且的Node.js过程退出.

const myEmitter = new MyEmitter();
myEmitter.emit('error', new Error('whoops!'));
// Throws and crashes Node.js

为了防止Node.js进程崩溃,可以使用domain模块. (但是请注意,不建议使用domain模块.)

作为最佳实践,应该始终为'error'事件添加侦听器.

const myEmitter = new MyEmitter();
myEmitter.on('error', (err) => {
  console.error('whoops! there was an error');
});
myEmitter.emit('error', new Error('whoops!'));
// Prints: whoops! there was an error

Class: EventEmitter#

EventEmitter类由events模块定义和公开:

const EventEmitter = require('events');

当添加新的侦听器时,所有EventEmitter都会发出事件'newListener' ,而当现有的侦听器被删除时,所有EventEmitter都会发出'removeListener'事件.

Event: 'newListener'#

在将侦听器添加到其内部侦听器数组之前EventEmitter实例将发出自己的'newListener'事件.

Listeners registered for the 'newListener' event will be passed the event name and a reference to the listener being added.

该事件被触发之前添加监听器有一个微妙但重要的副作用的事实:注册到同一任何额外的听众name 'newListener'回调将是在添加的过程中,听者之前插入.

const myEmitter = new MyEmitter();
// Only do this once so we don't loop forever
myEmitter.once('newListener', (event, listener) => {
  if (event === 'event') {
    // Insert a new listener in front
    myEmitter.on('event', () => {
      console.log('B');
    });
  }
});
myEmitter.on('event', () => {
  console.log('A');
});
myEmitter.emit('event');
// Prints:
//   B
//   A

Event: 'removeListener'#

删除listener后,将发出'removeListener'事件.

EventEmitter.listenerCount(emitter, eventName)#

稳定性:0-不建议使用:改为使用emitter.listenerCount() .

一个类方法,该方法返回在给定的emitter上注册的给定eventName的侦听emitter .

const myEmitter = new MyEmitter();
myEmitter.on('event', () => {});
myEmitter.on('event', () => {});
console.log(EventEmitter.listenerCount(myEmitter, 'event'));
// Prints: 2

EventEmitter.defaultMaxListeners#

默认情况下,任何单个事件最多可以注册10侦听器. 可以使用emitter.setMaxListeners(n)方法为单个EventEmitter实例更改此限制. 要更改所有 EventEmitter实例的默认值,可以使用EventEmitter.defaultMaxListeners属性. 如果此值不是正数,则将引发TypeError .

设置EventEmitter.defaultMaxListeners时请小心,因为更改会影响所有 EventEmitter实例,包括在更改之前创建的实例. 但是,调用emitter.setMaxListeners(n)仍然优先于EventEmitter.defaultMaxListeners .

请注意,这不是硬性限制. EventEmitter实例将允许添加更多的侦听器,但将向stderr输出跟踪警告,指示已检测到"可能的EventEmitter内存泄漏". 对于任何单个EventEmitter ,可以使用emitter.getMaxListeners()emitter.setMaxListeners()方法暂时避免此警告:

emitter.setMaxListeners(emitter.getMaxListeners() + 1);
emitter.once('event', () => {
  // do stuff
  emitter.setMaxListeners(Math.max(emitter.getMaxListeners() - 1, 0));
});

--trace-warnings命令行标志可用于显示此类警告的堆栈跟踪.

发出的警告可以使用process.on('warning')进行检查,并将具有附加的emittertypecount属性,分别引用事件发射器实例,事件的名称和附加的侦听器的数量. 它的name属性设置为'MaxListenersExceededWarning' .

emitter.addListener(eventName, listener)#

Alias for emitter.on(eventName, listener).

emitter.emit(eventName[, ...args])#

同步调用每一个名为事件注册的侦听器eventName ,他们的顺序进行了登记,通过所提供的参数,以每个.

Returns true if the event had listeners, false otherwise.

emitter.eventNames()#

返回一个数组,该数组列出发射器已为其注册侦听器的事件. 数组中的值将是字符串或Symbol .

const EventEmitter = require('events');
const myEE = new EventEmitter();
myEE.on('foo', () => {});
myEE.on('bar', () => {});

const sym = Symbol('symbol');
myEE.on(sym, () => {});

console.log(myEE.eventNames());
// Prints: [ 'foo', 'bar', Symbol(symbol) ]

emitter.getMaxListeners()#

返回EventEmitter的当前最大侦听器值,该值可以由emitter.setMaxListeners(n)设置,或者默认为EventEmitter.defaultMaxListeners .

emitter.listenerCount(eventName)#

返回侦听名为eventName的事件的侦听器的数量.

emitter.listeners(eventName)#

返回名为eventName的事件的侦听器数组的副本.

server.on('connection', (stream) => {
  console.log('someone connected!');
});
console.log(util.inspect(server.listeners('connection')));
// Prints: [ [Function] ]

emitter.off(eventName, listener)#

emitter.removeListener()别名.

emitter.on(eventName, listener)#

listener功能添加到名为eventName的事件的侦听器数组的末尾. 不检查是否已添加listener . 多次调用传递相同的eventNamelistener组合将导致多次添加和调用该listener器.

server.on('connection', (stream) => {
  console.log('someone connected!');
});

返回对EventEmitter的引用,以便可以链接调用.

默认情况下,事件侦听器按照添加顺序被调用. 可以使用emitter.prependListener()方法将事件侦听器添加到侦听器数组的开头.

const myEE = new EventEmitter();
myEE.on('foo', () => console.log('a'));
myEE.prependListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
//   b
//   a

emitter.once(eventName, listener)#

为名为eventName的事件添加一次性 listener函数. 下次触发eventName ,将删除此侦听器,然后调用它.

server.once('connection', (stream) => {
  console.log('Ah, we have our first user!');
});

返回对EventEmitter的引用,以便可以链接调用.

默认情况下,事件侦听器按照添加顺序被调用. emitter.prependOnceListener()方法可以用作将事件侦听器添加到侦听器数组的开头的替代方法.

const myEE = new EventEmitter();
myEE.once('foo', () => console.log('a'));
myEE.prependOnceListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
//   b
//   a

emitter.prependListener(eventName, listener)#

将名为eventName的事件的listener功能添加到侦听器数组的开头 . 不检查是否已添加listener . 多次调用传递相同的eventNamelistener组合将导致多次添加和调用该listener器.

server.prependListener('connection', (stream) => {
  console.log('someone connected!');
});

返回对EventEmitter的引用,以便可以链接调用.

emitter.prependOnceListener(eventName, listener)#

将名为eventName的事件的一次性 listener函数添加到侦听器数组的开头 . 下次触发eventName ,将删除此侦听器,然后将其调用.

server.prependOnceListener('connection', (stream) => {
  console.log('Ah, we have our first user!');
});

返回对EventEmitter的引用,以便可以链接调用.

emitter.removeAllListeners([eventName])#

删除所有侦听器,或指定的eventName侦听器.

请注意,删除在代码中其他位置添加的侦听器是一种不好的做法,尤其是在EventEmitter实例是由某些其他组件或模块(例如套接字或文件流)创建时.

返回对EventEmitter的引用,以便可以链接调用.

emitter.removeListener(eventName, listener)#

删除指定listener来自监听器阵列名为事件eventName .

const callback = (stream) => {
  console.log('someone connected!');
};
server.on('connection', callback);
// ...
server.removeListener('connection', callback);

removeListener()最多将从侦听器数组中删除一个侦听器实例. 如果已将任何单个侦听器多次添加到指定eventName的侦听器数组,则必须多次调用removeListener()才能删除每个实例.

请注意,一旦事件被发出,在发出事件时连接到它的所有侦听器将被依次调用. 这意味着发出之后且最后一个侦听器执行完成之前 ,任何removeListener()removeAllListeners()调用都不会将它们从正在进行的emit()中移除. 随后的事件将按预期方式运行.

const myEmitter = new MyEmitter();

const callbackA = () => {
  console.log('A');
  myEmitter.removeListener('event', callbackB);
};

const callbackB = () => {
  console.log('B');
};

myEmitter.on('event', callbackA);

myEmitter.on('event', callbackB);

// callbackA removes listener callbackB but it will still be called.
// Internal listener array at time of emit [callbackA, callbackB]
myEmitter.emit('event');
// Prints:
//   A
//   B

// callbackB is now removed.
// Internal listener array [callbackA]
myEmitter.emit('event');
// Prints:
//   A

由于使用内部数组管理侦听器,因此调用此方法将更改删除侦听器注册的所有侦听器的位置索引. 这不会影响侦听器的调用顺序,但是这意味着需要重新创建emitter.listeners()方法返回的侦听器数组的任何副本.

当已将单个函数多次添加为单个事件的处理程序时(如下面的示例所示), removeListener()将删除最近添加的实例. 在该示例中, once('ping')侦听器被删除:

const ee = new EventEmitter();

function pong() {
  console.log('pong');
}

ee.on('ping', pong);
ee.once('ping', pong);
ee.removeListener('ping', pong);

ee.emit('ping');
ee.emit('ping');

返回对EventEmitter的引用,以便可以链接调用.

emitter.setMaxListeners(n)#

默认情况下,如果为特定事件添加了10侦听器,则EventEmitter会打印警告. 这是一个有用的默认值,有助于查找内存泄漏. 显然,并非所有事件都应仅限于10个侦听器. emitter.setMaxListeners()方法允许为此特定EventEmitter实例修改限制. 该值可以设置为Infinity (或0 )以指示无限数量的侦听器.

返回对EventEmitter的引用,以便可以链接调用.

emitter.rawListeners(eventName)#

返回名为eventName的事件的侦听器数组的副本,包括所有包装(如.once()创建的.once() ).

const emitter = new EventEmitter();
emitter.once('log', () => console.log('log once'));

// Returns a new Array with a function `onceWrapper` which has a property
// `listener` which contains the original listener bound above
const listeners = emitter.rawListeners('log');
const logFnWrapper = listeners[0];

// Logs "log once" to the console and does not unbind the `once` event
logFnWrapper.listener();

// Logs "log once" to the console and removes the listener
logFnWrapper();

emitter.on('log', () => console.log('log persistently'));
// Will return a new Array with a single function bound by `.on()` above
const newListeners = emitter.rawListeners('log');

// logs "log persistently" twice
newListeners[0]();
emitter.emit('log');

events.once(emitter, name)[src]#

创建一个Promise ,当EventEmitter发出给定事件时解决该Promise ,或者当EventEmitter发出'error'时拒绝该EventEmitter . Promise将使用给定事件发出的所有参数的数组进行解析.

const { once, EventEmitter } = require('events');

async function run() {
  const ee = new EventEmitter();

  process.nextTick(() => {
    ee.emit('myevent', 42);
  });

  const [value] = await once(ee, 'myevent');
  console.log(value);

  const err = new Error('kaboom');
  process.nextTick(() => {
    ee.emit('error', err);
  });

  try {
    await once(ee, 'myevent');
  } catch (err) {
    console.log('error happened', err);
  }
}

run();

by  ICOPY.SITE