繁体   English   中英

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

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

如何从事件侦听器返回值?

请参见下面的示例:

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"

我想修改事件值并返回修改后的版本。

我该怎么做?

事件处理程序的返回值完全被忽略。 文档

EventEmitter对象发出事件时,将同步调用附加到该特定事件的所有函数。 被调用者返回的任何值都将被忽略,并将被丢弃。

但你可以做的是发出一个对象并让回调修改该对象的状态:

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"

(还要注意的变化产生的实例EventEmitter ;你原来的代码试图利用onEventEmitter本身,而是它没有一个。)


您在评论中已经说过,您希望避免将对象创建为自己的步骤。 您可以轻松地将EventEmitter子类EventEmitter添加自己的emitObject (或其他)函数:

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"

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

完整的例子:

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"

如果你只想有一个“返回”值,只需使用回调 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);
})();

或者只是添加另一个侦听器作为应答侦听器:

因此,我能够通过创建自定义版本的EventEmitter来做到这一点。 我添加了一个新方法来将发出的事件注册为挂起并返回一个 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