Node.js: how can I return a value from an event listener?

Hasan Bayat picture Hasan Bayat · Mar 15, 2017 · Viewed 9.9k times · Source

How to i return value from the an event listeners?

See example below:

const EventEmitter = require("events").EventEmitter;
emitter = new EventEmitter();
emitter.on("sayHello", function(message) {
    return message + " World";
});
let helloMessage = emitter.emit("sayHello", "Hello");
console.log(helloMessage); // It should output: "Hello World"

I want to modify event value and return the modified version.

How do i do it?

Answer

T.J. Crowder picture T.J. Crowder · Mar 15, 2017

The return value of event handlers is completely ignored. From the documentation:

When the EventEmitter object emits an event, all of the functions attached to that specific event are called synchronously. Any values returned by the called listeners are ignored and will be discarded.

But what you can do instead is emit an object and have the callback modify the state of that object:

const EventEmitter = require("events").EventEmitter;
const emitter = new EventEmitter();
emitter.on("sayHello", function(e) {
    e.message += " World";              // Modifying the state
});
const e = {message: "Hello"};
emitter.emit("sayHello", e);
console.log(e.message); // "Hello World"

(Also note the changes creating an instance of EventEmitter; your original code tried to use on on EventEmitter itself, but it doesn't have one.)


You've said in the comments that you would like to avoid having to create the object as its own step. You can easily subclass EventEmitter to add your own emitObject (or whatever) function:

class MyEventEmitter extends EventEmitter {
    emitObject(event, obj = {}) {
        this.emit(event, obj);
        return obj;
    }
}

Usage:

const emitter = new MyEventEmitter();
emitter.on("sayHello", function(e) {
    e.message += " World";
});
const evt = emitter.emitObject("sayHello", {message: "Hello"});
console.log(evt.message); // "Hello World"

I've supplied an object for the second argument there (so we could do the "Hello" + " World" thing), but if you left it off, a blank object would be defaulted for it (ES2015 default arguments).

Complete example:

const EventEmitter = require("events").EventEmitter;
class MyEventEmitter extends EventEmitter {
    emitObject(event, obj = {}) {
        this.emit(event, obj);
        return obj;
    }
}
const emitter = new MyEventEmitter();
emitter.on("sayHello", function(e) {
    e.message += " World";
});
const evt = emitter.emitObject("sayHello", {message: "Hello"});
console.log(evt.message); // "Hello World"