Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How should you inherit from EventEmitter in node?

I was reading over this small article to understand inheriting from EventEmitter, but I'm a little confused.

He does this:

function Door() {
    events.EventEmitter.call(this);
    this.open = function() {
        this.emit('open');
    };
}
Door.prototype.__proto__ = events.EventEmitter.prototype;

https://gist.github.com/chevex/7646362

Why does he manually invoke the EventEmitter constructor with his own constructor's this? Also, why does he set the prototype of his contsructor's prototype to the prototype of EventEmitter? That's super confusing to me.

Then someone in the comments suggested he do this instead, which seemed more elegant:

function Door() {
    events.EventEmitter.call(this);
    this.open = function () {
      this.emit('open');
    }
}
util.inherits(Door, events.EventEmitter);

https://gist.github.com/chevex/7646447

This seems WAY cleaner than the other way, though that's probably just because I fail to understand what's going on in the first instance. I would not be surprised if util.inherits is doing the same thing as the first example.

The second one at least makes a little sense to me, but I still don't understand why they don't just do this:

function Door() {
    this.open = function () {
      this.emit('open');
    }
}
Door.prototype = new events.EventEmitter();

https://gist.github.com/chevex/7646524

Can anyone explain to me what the differences between all of these approaches is and why in the first two they invoke .call(this) on the EventEmitter constructor? I omitted that line while trying out the examples and they still worked.

like image 374
Chev Avatar asked Nov 25 '13 18:11

Chev


People also ask

How do I inherit in node JS?

You can use Object. create() to inherit one object to another in Node. js also. console.

What is used to returning from EventEmitter object?

Finally, we return an object of EventEmitter from the function. So now, we can use the return value of LoopProcessor function to bind these events using on() or addListener() function.

When should I use EventEmitter in node JS?

Use event emitter if you need to notify the user of a state change. For testing purpose, if you want to make sure a function is called inside a function, emit an event.

What is EventEmitter and how is it used in Node JS?

The EventEmitter is a module that facilitates communication/interaction between objects in Node. EventEmitter is at the core of Node asynchronous event-driven architecture. Many of Node's built-in modules inherit from EventEmitter including prominent frameworks like Express.


2 Answers

The Node v6.3.1 documentation states about util.inherits(constructor, superConstructor):

Usage of util.inherits() is discouraged. Please use the ES6 class and extends keywords to get language level inheritance support. Also note that the two styles are semantically incompatible.


The following code shows how to inherit from EventEmitter with Typescript:

import { EventEmitter } from "events"

class Person extends EventEmitter {
    constructor(public name: string) {
        super()
    }
}

let person = new Person("Bob")
person.on("speak", function (said: string) {
    console.log(`${this.name} said: ${said}`)
})
person.emit("speak", "'hello'") // prints "Bob said: 'hello'"

The previous code will transpile into the following ES6 code:

"use strict";
const events = require("events");
class Person extends events.EventEmitter {
    constructor(name) {
        super();
        this.name = name;
    }
}
let person = new Person("Bob");
person.on("speak", function (said) { console.log(`${this.name} said: ${said}`); });
person.emit("speak", "'hello'");
like image 139
2 revs Avatar answered Sep 30 '22 11:09

2 revs


function Door() {
    events.EventEmitter.call(this);
}

Door.prototype.__proto__ = events.EventEmitter.prototype;

In this case using events.EventEmitter.call(this) is like using super in languages which have one. It's actually can be omitted in simple cases, but it will break domain support on current node version and maybe something else in future versions.

Setting __proto__ just sets up the prototype chain. At can be also done like this:

Door.prototype = Object.create(events.EventEmitter.prototype);

but in this case you also need to set constructor property manually.

util.inherits(Door, events.EventEmitter);

This is the idiomatic way of inheriting in node. So you are better to use this. But what it does is basically the same as above.

function Door() {
}
Door.prototype = new events.EventEmitter();

And this is the WRONG way, don't use it! You will end with having events shared between instances in some versions of node.

like image 32
vkurchatkin Avatar answered Sep 30 '22 13:09

vkurchatkin