89 lines
		
	
	
	
		
			2.7 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
		
		
			
		
	
	
			89 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')
							 | 
						||
| 
								 | 
							
								````
							 |