| # Events |
| |
| Stability: 2 - Stable |
| |
| <!--type=module--> |
| |
| 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. |
| |
| const EventEmitter = require('events'); |
| const util = require('util'); |
| |
| function MyEmitter() { |
| EventEmitter.call(this); |
| } |
| util.inherits(MyEmitter, EventEmitter); |
| |
| const myEmitter = new MyEmitter(); |
| myEmitter.on('event', function() { |
| console.log('an event occurred!'); |
| }); |
| myEmitter.emit('event'); |
| |
| Any object can become an `EventEmitter` through inheritance. The example above |
| uses the traditional Node.js style prototypical inheritance using |
| the `util.inherits()` method. It is, however, possible to use ES6 classes as |
| well: |
| |
| const EventEmitter = require('events'); |
| |
| class MyEmitter extends EventEmitter {} |
| |
| const myEmitter = new MyEmitter(); |
| myEmitter.on('event', function() { |
| 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. |
| |
| 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: |
| |
| 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 immediately unregistered after it is 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 a special case |
| 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, developers can either register |
| a listener for the `process.on('uncaughtException')` event or use the |
| [`domain`][] module (_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, developers should always register listeners for the |
| `'error'` event: |
| |
| 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 |
| |
| ## Class: EventEmitter |
| |
| The `EventEmitter` class is defined and exposed by the `events` module: |
| |
| const EventEmitter = require('events'); |
| |
| All EventEmitters emit the event `'newListener'` when new listeners are |
| added and `'removeListener'` when a listener is removed. |
| |
| ### Event: 'newListener' |
| |
| * `event` {String|Symbol} The event name |
| * `listener` {Function} The event handler function |
| |
| The `EventEmitter` instance will emit it's own `'newListener'` event *before* |
| a listener is added to it's internal array of listeners. |
| |
| Listeners registered for the `'newListener'` event will be passed the event |
| name and a reference to the listener being added. |
| |
| The fact that the event is triggered before adding the listener has a subtle |
| but important side effect: any *additional* listeners registered to the same |
| `name` *within* the `'newListener'` callback will be inserted *before* the |
| listener that is in the process of being added. |
| |
| 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' |
| |
| * `event` {String|Symbol} The event name |
| * `listener` {Function} The event handler function |
| |
| The `'removeListener'` event is emitted *after* a listener is removed. |
| |
| ### EventEmitter.listenerCount(emitter, event) |
| |
| Stability: 0 - Deprecated: Use [`emitter.listenerCount()`][] instead. |
| |
| A class method that returns the number of listeners for the given `event` |
| registered on the given `emitter`. |
| |
| const myEmitter = new MyEmitter(); |
| myEmitter.on('event', () => {}); |
| myEmitter.on('event', () => {}); |
| console.log(EventEmitter.listenerCount(myEmitter, 'event')); |
| // Prints: 2 |
| |
| ### EventEmitter.defaultMaxListeners |
| |
| By default, a maximum of `10` listeners can be registered for any single |
| event. This limit can be changed for individual `EventEmitter` instances |
| using the [`emitter.setMaxListeners(n)`][] method. To change the default |
| for *all* `EventEmitter` instances, the `EventEmitter.defaultMaxListeners` |
| property can be used. |
| |
| Take caution when setting the `EventEmitter.defaultMaxListeners` because the |
| change effects *all* `EventEmitter` instances, including those created before |
| the change is made. However, calling [`emitter.setMaxListeners(n)`][] still has |
| precedence over `EventEmitter.defaultMaxListeners`. |
| |
| Note that this is not a hard limit. The `EventEmitter` instance will allow |
| more listeners to be added but will output a trace warning to stderr indicating |
| that a `possible EventEmitter memory leak` has been detected. For any single |
| `EventEmitter`, the `emitter.getMaxListeners()` and `emitter.setMaxListeners()` |
| methods can be used to temporarily avoid this warning: |
| |
| emitter.setMaxListeners(emitter.getMaxListeners() + 1); |
| emitter.once('event', () => { |
| // do stuff |
| emitter.setMaxListeners(Math.max(emitter.getMaxListeners() - 1, 0)); |
| }); |
| |
| ### emitter.addListener(event, listener) |
| |
| Alias for `emitter.on(event, listener)`. |
| |
| ### emitter.emit(event[, arg1][, arg2][, ...]) |
| |
| Synchronously calls each of the listeners registered for `event`, in the order |
| they were registered, passing the supplied arguments to each. |
| |
| Returns `true` if event had listeners, `false` otherwise. |
| |
| ### emitter.getMaxListeners() |
| |
| Returns the current max listener value for the `EventEmitter` which is either |
| set by [`emitter.setMaxListeners(n)`][] or defaults to |
| [`EventEmitter.defaultMaxListeners`][]. |
| |
| ### emitter.listenerCount(event) |
| |
| * `event` {Value} The type of event |
| |
| Returns the number of listeners listening to the `event` type. |
| |
| ### emitter.listeners(event) |
| |
| Returns a copy of the array of listeners for the specified `event`. |
| |
| server.on('connection', (stream) => { |
| console.log('someone connected!'); |
| }); |
| console.log(util.inspect(server.listeners('connection'))); |
| // Prints: [ [Function] ] |
| |
| ### emitter.on(event, listener) |
| |
| Adds the `listener` function to the end of the listeners array for the |
| specified `event`. No checks are made to see if the `listener` has already |
| been added. Multiple calls passing the same combination of `event` and |
| `listener` will result in the `listener` being added, and called, multiple |
| times. |
| |
| server.on('connection', (stream) => { |
| console.log('someone connected!'); |
| }); |
| |
| Returns a reference to the `EventEmitter` so calls can be chained. |
| |
| ### emitter.once(event, listener) |
| |
| Adds a **one time** `listener` function for the `event`. This listener is |
| invoked only the next time `event` is triggered, after which it is removed. |
| |
| server.once('connection', (stream) => { |
| console.log('Ah, we have our first user!'); |
| }); |
| |
| Returns a reference to the `EventEmitter` so calls can be chained. |
| |
| ### emitter.removeAllListeners([event]) |
| |
| Removes all listeners, or those of the specified `event`. |
| |
| Note that it is bad practice to remove listeners added elsewhere in the code, |
| particularly when the `EventEmitter` instance was created by some other |
| component or module (e.g. sockets or file streams). |
| |
| Returns a reference to the `EventEmitter` so calls can be chained. |
| |
| ### emitter.removeListener(event, listener) |
| |
| Removes the specified `listener` from the listener array for the specified |
| `event`. |
| |
| var callback = function(stream) { |
| console.log('someone connected!'); |
| }; |
| server.on('connection', callback); |
| // ... |
| server.removeListener('connection', callback); |
| |
| `removeListener` will remove, at most, one instance of a listener from the |
| listener array. If any single listener has been added multiple times to the |
| listener array for the specified `event`, then `removeListener` must be called |
| multiple times to remove each instance. |
| |
| Because listeners are managed using an internal array, calling this will |
| change the position indices of any listener registered *after* the listener |
| being removed. This will not impact the order in which listeners are called, |
| but it will means that any copies of the listener array as returned by |
| the `emitter.listeners()` method will need to be recreated. |
| |
| Returns a reference to the `EventEmitter` so calls can be chained. |
| |
| ### emitter.setMaxListeners(n) |
| |
| By default EventEmitters will print a warning if more than `10` listeners are |
| added for a particular event. This is a useful default that helps finding |
| memory leaks. Obviously, not all events should be limited to just 10 listeners. |
| The `emitter.setMaxListeners()` method allows the limit to be modified for this |
| specific `EventEmitter` instance. The value can be set to `Infinity` (or `0`) |
| for to indicate an unlimited number of listeners. |
| |
| Returns a reference to the `EventEmitter` so calls can be chained. |
| |
| [`net.Server`]: net.html#net_class_net_server |
| [`fs.ReadStream`]: fs.html#fs_class_fs_readstream |
| [`emitter.setMaxListeners(n)`]: #events_emitter_setmaxlisteners_n |
| [`EventEmitter.defaultMaxListeners`]: #events_eventemitter_defaultmaxlisteners |
| [`emitter.listenerCount()`]: #events_emitter_listenercount_event |
| [`domain`]: domain.html |
| [stream]: stream.html |