Saturday, November 2, 2019

NodeJs: Event emitter: Synchronous - Asynchronous

We generally use Event emitter class in NodeJs to implement publish subscribe mechanism. Most of us think that this event emitter works totally in asynchronous way. But, its not true. If we take it in scenario wise, we can get two scenarios:

Scenario 1) Suppose event emitter class is emitting two different events say "event1" and "event2". Here, we usually think that the handlers of both of these events will run asynchronously. But, the fact is that which ever event is triggered first, its handler will run first irrespective of the fact that which event handler is associated first with the event emitter object. e.g.

const EventEmitter = require('events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event1', handleEvent1);
myEmitter.on('event2', handleEvent2);
function handleEvent1() {
console.log('an event1 started!');
  let x=0;
  for(let i=0; i<100; i++){
x = x + i;
  }
  console.log('an event1 ended!');
}
function handleEvent2() {
console.log('an event2 started!');
  let x=0;
  for(let i=0; i<1000000000; i++){
x = x + i;
  }
  console.log('an event2 ended!');
}
myEmitter.emit('event2');
myEmitter.emit('event1');
 The output of the above code is:

C:\Users\singh\Desktop\delete2>node event-emit-test2
an event2 started!
an event2 ended!
an event1 started!
an event1 ended!
From above output, its clear that "event2" is being triggered first and although its handler is taking more time as compared to handler of "event1", but till the time handler of event2 is running, the handler of event1 is waiting. So, here whichever event is triggered first, it will complete first.

Scenario 2) Suppose event emitter is emitting same event 2 times and two different handlers are associated with the same event. So, here the rhythm of association matters and which ever handler is associated first, will complete first then the second event handler will start. e.g.

const EventEmitter = require('events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', handleEvent1);
myEmitter.on('event', handleEvent2);
function handleEvent1() {
console.log('an event1 started!');
  let x=0;
  for(let i=0; i<1000000000; i++){
x = x + i;
  }
  console.log('an event1 ended!');
}
function handleEvent2() {
console.log('an event2 started!');
  let x=0;
  for(let i=0; i<10; i++){
x = x + i;
  }
  console.log('an event2 ended!');
}
myEmitter.emit('event');
The output is:
C:\Users\singh\Desktop\delete2>node event-emit-test2
an event1 started!
an event1 ended!
an event2 started!
an event2 ended!
Here, the output is clearly showing that in this scenario, the rhythm of event handler association is being followed and handlers are running in Synchronous way.

If needed we can force these handlers to run in asynchronous way by using "setImmediate" and "process.nextTick". e.g.

const EventEmitter = require('events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', () => setImmediate(handleEvent1));
myEmitter.on('event', () => process.nextTick(handleEvent2));
function handleEvent1() {
console.log('an event1 started!');
  let x=0;
  for(let i=0; i<100; i++){
x = x + i;
  }
  console.log('an event1 ended!');
}
function handleEvent2() {
console.log('an event2 started!');
  let x=0;
  for(let i=0; i<1000000000; i++){
x = x + i;
  }
  console.log('an event2 ended!');
}
myEmitter.emit('event');
The output is:
C:\Users\singh\Desktop\delete2>node event-emit-test
an event2 started!
an event2 ended!
an event1 started!
an event1 ended!
It is clear from output that even if handleEvent1 is associated first and handleEvent2 is associated 2nd with event named as "event", but handleEvent2 is being triggered and completed first based on "setImmediate" and "process.nextTick".

No comments:

Post a Comment

Please provide your precious comments and suggestion