//

Thursday, June 27, 2019

Event emitters

 Understanding Event Emitters

Understanding Event Emitters

Event emitters is a core module for Node developers to implement the observer pattern. The observer pattern has the following: an observer, an event and an event emitter.
The flow goes like this:
  1. A class is created with class
  2. A class inherits from the EventEmitter class using extends
  3. An instance of an object is created from the class with new
  4. An observer (a.k.a. event listener) is created with .on(eventName, eventHandler)
  5. An event is emitted with emit() and the event handler in the observer is executed.
Consider this simple observer pattern code which creates a Job class and then instantiates it. Later on, the object created from the class has an observer/event listener attached (job.on('done'...)) and an event is emitted/triggered.
simple.js:
const EventEmitter = require('events')

class Job extends EventEmitter {}
job = new Job()

job.on('done', function(timeDone){
  console.log('Job was pronounced done at', timeDone)
})

job.emit('done', new Date())
job.removeAllListeners()  // remove  all observers
The result will be:
Job was pronounced done at

Multiple Event Triggers

Events can be triggered/emitted multiple times. For example, in knock-knock.js the knock event is emitted multiple times.
knock-knock.js:
const EventEmitter = require('events')

class Emitter extends EventEmitter {}
emitter = new Emitter()

emitter.on('knock', function() {
  console.log('Who\'s there?')
})

emitter.on('knock', function() {
  console.log('Go away!')
})

emitter.emit('knock')
emitter.emit('knock')
The result will be:
Who's there?
Go away!
Who's there?
Go away!

Executing Observer Code Only once

emitter.once(eventName, eventHandler) will execute observer code just once, no matter how many time this particular event was triggered.
knock-knock-once.js:
const EventEmitter = require('events')

class Emitter extends EventEmitter {}
emitter = new Emitter()

emitter.once('knock', function() {
  console.log('Who\'s there?')
})


emitter.emit('knock')
emitter.emit('knock')
The result will be:
Who's there?


Modular Events

The observer pattern is often used to modularize code. A typical usage is to separate the event emitter class definition and the event emission into its own module but allow the observers to be defined in the main program. This allows us to customize the module behavior without changing the module code itself.
In job.js, we use a generic job module that emits a done event after 700ms. However, in weekly.js, we can customize the event handler of the observer to do whatever we want once a done event is triggered.
job.js:
const EventEmitter = require('events')
class Job extends EventEmitter {
  constructor(ops) {
    super(ops)
    this.on('start', ()=>{
      this.process()
    })
  }
  process() {
     setTimeout(()=>{
      // Emulate the delay of the job - async!
      this.emit('done', { completedOn: new Date() })
    }, 700)
  }
}

module.exports = Job
weekly.js:
var Job = require('./job.js')
var job = new Job()

job.on('done', function(details){
  console.log('Weekly email job was completed at',
    details.completedOn)
})

job.emit('start')
When you run weekly.js, the custom logic pertaining to the done event will be executed from weekly.js. This way the creators of the job.jsmodule can keep the module flexible. They don't have to hard code any logic for the done event in the module. Consumers of the module job.js, people who write weekly.js, have the power to customize the behavior for the done event, and not only for that event. Event emitters can have multiple events: in the middle, at the start, in the end, etc. They can be called (emitted or triggered) multiple times and with data (passed as the second argument to emit() as can be seen in job.js). Furthermore, there are methods to list or remove event listeners (observers) or to specify the execution of an event listener (observer) just once (.once() method).

No comments:

Post a Comment

Effective Branching Strategies in Development Teams

Effective Branching Strategies in Development Teams Effective Branching Strategies in Developme...