zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Node.js Events模块

JSNode模块 Events
2023-09-11 14:22:55 时间

Node.js v7.4.0 Documentation

  • Events
    • Passing arguments and this to listeners
    • Asynchronous vs. Synchronous
    • Handling events only once
    • Error events
    • Class: EventEmitter
      • Event: ‘newListener’
      • Event: ‘removeListener’
      • EventEmitter.defaultMaxListeners
      • emitter.addListener(eventName, listener)
      • emitter.emit(eventName[, …args])
      • emitter.eventNames()
      • emitter.getMaxListeners()
      • emitter.listenerCount(eventName)
      • emitter.listeners(eventName)
      • emitter.on(eventName, listener)
      • emitter.once(eventName, listener)
      • emitter.prependListener(eventName, listener)
      • emitter.prependOnceListener(eventName, listener)
      • emitter.removeAllListeners([eventName])
      • emitter.removeListener(eventName, listener)
      • emitter.setMaxListeners(n)

Events

Stability: 2 - Stable

Much of the Node.js core API is built around an idiomatic asynchronous event-driven architecture in which certain kinds of objects (called “emitters”) periodically emit named events that cause Function objects (“listeners”) to be called.

For instance: a net.Server object emits an event each time a peer connects to it; a fs.ReadStream emits an event when the file is opened; a stream emits an event whenever data is available to be read.

All objects that emit events are instances of the EventEmitter class. These objects expose an eventEmitter.on() function that allows one or more functions to be attached to named events emitted by the object. Typically, event names are camel-cased strings but any valid JavaScript property key can be used.

When the EventEmitter object emits an event, all of the functions attached to that specific event are called synchronously. Any values returned by the called listeners are ignored and will be discarded.

The following example shows a simple EventEmitter instance with a single listener. The eventEmitter.on() method is used to register listeners, while the eventEmitter.emit() method is used to trigger the event.

大部分Node.js内核API都围绕着一个符合语言习惯的异步事件驱动架构来编译,它包含了各种各样的叫“emitters”的对象,周期性的发射该名称的事件,导致“listeners”的函数对象被调用。

举个例子:当一个对等体连接上它的时候,一个net.Server对象每次都发送一个事件。当文件被打开时,fs.ReadStream发射一个事件。当数据可读时,一个stream发射一个事件。

所有可以发射事件的对象都是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

The eventEmitter.emit() method allows an arbitrary set of arguments to be passed to the listener functions. It is important to keep in mind that when an ordinary listener function is called by the EventEmitter, the standard this keyword is intentionally set to reference the EventEmitter to which the listener is attached.

eventEmitter.emit()方法允许随意设置传递给监听器函数的仓鼠。重要的是要记住当一个普通的监听函数被EventEmitter调用时,标准的this关键字会被有意的设置到监听器附加到EventEmitter的引用上。

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

It is possible to use ES6 Arrow Functions as listeners, however, when doing so, the this keyword will no longer reference the EventEmitter instance:

可以使用ES6(ECMAScript 6)允许的函数作为监听器,然后当这样做的时候,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

The EventListener calls all listeners synchronously in the order in which they were registered. This is important to ensure the proper sequencing of events and to avoid race conditions or logic errors. When appropriate, listener functions can switch to an asynchronous mode of operation using the setImmediate() or process.nextTick() methods:

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

Handling events only once

When a listener is registered using the eventEmitter.on() method, that listener will be invoked every time the named event is emitted.

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

Using the eventEmitter.once() method, it is possible to register a listener that is called at most once for a particular event. Once the event is emitted, the listener is unregistered and then called.

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

Error events

When an error occurs within an EventEmitter instance, the typical action is for an ‘error’ event to be emitted. These are treated as special cases within Node.js.

If an EventEmitter does not have at least one listener registered for the ‘error’ event, and an ‘error’ event is emitted, the error is thrown, a stack trace is printed, and the Node.js process exits.

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

To guard against crashing the Node.js process, a listener can be registered on the process object’s uncaughtException event or the domain module can be used. (Note, however, that the domain module has been deprecated)

const myEmitter = new MyEmitter();

process.on('uncaughtException', (err) => {
  console.log('whoops! there was an error');
});

myEmitter.emit('error', new Error('whoops!'));
  // Prints: whoops! there was an error

As a best practice, listeners should always be added for the ‘error’ events.

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