88 lines
2.7 KiB
Markdown
88 lines
2.7 KiB
Markdown
---
|
|
tags:
|
|
- Programming_Languages
|
|
- backend
|
|
- node-js
|
|
- node-modules
|
|
---
|
|
|
|
* Much of the NodeJS core is built around an [asynchronous event-driven architecture](Single-threaded%20asynchronous%20architecture.md) in which certain kinds of objects (called "emitters") emit named events that cause `Function` objects ("listeners") to be called.
|
|
* For example: a `fs.ReadStream` emits an event when the file is opened
|
|
|
|
## Event Emitters
|
|
|
|
* 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.
|
|
* These functions are listeners of the emitter.
|
|
|
|
## Basic syntax
|
|
|
|
````js
|
|
const EventEmitter = require('events') // import the module
|
|
|
|
// Raise an event
|
|
const emitter = new EventEmitter('messageLogged')
|
|
|
|
// Register a listener
|
|
emitter.on('messagedLogged', function() {
|
|
console.log('The listener was called.')
|
|
})
|
|
|
|
````
|
|
|
|
* If we ran this file, we would see `The listener was called` logged to the console.
|
|
* Without a listener (similar to a subscriber in Angular) nothing happens.
|
|
* When the emission occurs the emitter works *synchronously* through each listener function that is attached to it.
|
|
|
|
## Event arguments
|
|
|
|
* Typically we would not just emit a string, we would attach an object to the emitter to pass more useful data. This data is called an **Event Argument**.
|
|
* Refactoring the previous example:
|
|
|
|
````js
|
|
|
|
// Raise an event
|
|
const emitter = new EventEmitter('messageLogged', function(eventArg) {
|
|
console.log('Listener called', eventArg)
|
|
})
|
|
|
|
// Register a listener
|
|
emitter.on('messagedLogged', {id: 1, url: 'http://www.example.com'})
|
|
|
|
````
|
|
|
|
## Extending the `EventEmitter` class
|
|
|
|
* It's not best practice to call the EventEmitter class directly in `app.js`. If we want to use the capabilities of the class we should create our own module that extends `EventEmitter`, inheriting its functionality with specific additional features that we want to add.
|
|
* So, refactoring the previous example:
|
|
|
|
````js
|
|
// File: Logger.js
|
|
|
|
const EventEmitter = require('events')
|
|
|
|
class Logger extends EventEmitter {
|
|
log(message){
|
|
console.log(message)
|
|
this.emit('messageLogged', {id: 1, url: 'http://www.example.com'})
|
|
}
|
|
}
|
|
|
|
|
|
````
|
|
|
|
*The `this` in the `log` method refers to the properties and methods of `EventEmitter` which we have extended.*
|
|
|
|
* We also need to refactor our listener code within `app.js` so that it calls the extended class rather than the `EventEmitter` class directly:
|
|
|
|
````js
|
|
// File app.js
|
|
|
|
const Logger = require('./Logger')
|
|
const logger = new Logger()
|
|
|
|
logger.on('messageLogged', function(eventArg){
|
|
console.log('Listener called', eventArg)
|
|
}
|
|
|
|
logger.log('message')
|
|
````
|