简体   繁体   English

Node.js:如何从事件侦听器返回值?

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

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?我该怎么做?

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. EventEmitter对象发出事件时,将同步调用附加到该特定事件的所有函数。 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.) (还要注意的变化产生的实例EventEmitter ;你原来的代码试图利用onEventEmitter本身,而是它没有一个。)


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: 您可以轻松地将EventEmitter子类EventEmitter添加自己的emitObject (或其他)函数:

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). 我已经为那里的第二个参数提供了一个对象(所以我们可以做"Hello" + " World"事情),但是如果你把它关掉的话,一个空白对象就会被默认(ES2015默认参数)。

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"

If you just want to has a "return" value,just use callback function.如果你只想有一个“返回”值,只需使用回调 function。

const MyEmitter = require("events");
const myEmitter = new MyEmitter();
myEmitter.on("aaa", (callback) => {
  callback("123");
});
(async () => {
  const result = await new Promise((resolve) =>
    myEmitter.emit("aaa", (value) => {
      resolve(value);
    })
  );
  console.log(`result`, result);
})();

or just add another listener as answer listener:或者只是添加另一个侦听器作为应答侦听器:

So, I was able to do this by creating a custom version of the EventEmitter .因此,我能够通过创建自定义版本的EventEmitter来做到这一点。 I added a new method to register the emitted event as pending and return a promise that will resolve when the listener/handler for that event returns a value.我添加了一个新方法来将发出的事件注册为挂起并返回一个 promise,它将在该事件的侦听器/处理程序返回值时解析。

class MessageBus {
  #emitter = new EventEmitter();
  #pendingEventsRegistry = new Map<
    string | symbol,
    Array<(value: any) => void>
  >();

  public send<T>(eventName: string, message: any) {
    const result$ = new Promise<T>((resolve) => {
      const resolvers = this.#pendingEventsRegistry.get(eventName) ?? [];
      resolvers.push(resolve);
      this.#pendingEventsRegistry.set(eventName, resolvers);
    });
    this.#emitter.emit(eventName, message);
    return result$;
  }

  #execute(eventName: string | symbol, result: any) {
    const resolvers = this.#pendingEventsRegistry.get(eventName) ?? [];
    for (const resolve of resolvers) {
      resolve(result);
    }
    this.#pendingEventsRegistry.delete(eventName);
  }

  public on(eventName: string | symbol, listener: (...args: any[]) => void) {
    this.#emitter.on(eventName, (...args: any[]) => {
      const result = listener(...args);
      this.#execute(eventName, result);
    });
  }

  public once(eventName: string | symbol, listener: (...args: any[]) => void) {
    this.#emitter.once(eventName, (...args: any[]) => {
      const result = listener(...args);
      this.#execute(eventName, result);
    });
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM