【问题标题】:How to wait until multiple EventEmitter instances have emitted same event in Node.js?如何等到多个 EventEmitter 实例在 Node.js 中发出相同的事件?
【发布时间】:2017-09-08 20:08:06
【问题描述】:

我正在开发一个 Node.js 模块/实用程序,它将允许我搭建一些目录/文件。长话短说,现在我的主要功能看起来像这样:

util.scaffold("FileName")

这个“脚手架”方法返回一个 EventEmitter 实例,所以,当使用这个方法时,我可以这样做:

util.scaffold("Name")
.on("done", paths => console.log(paths)

换句话说,当所有文件都被创建时,事件“done”将被触发,并带有脚手架文件的所有路径。

到目前为止一切都很好。

现在,我正在尝试使用此方法进行一些测试和基准测试,并且在此“脚手架”方法被多次调用后,我正在尝试找到一种执行某些操作(断言、日志等)的方法使用不同的“名称”参数的时间。例如:

const names = ["Name1", "Name2", "Name3"] 
const emitters = names.map(name => {
return util.scaffold(name)
})

如果我返回的是 Promise 而不是 EventEmitter,我知道我可以这样做:

Promise.all(promises).then(()=> {
//perform assertions, logs, etc
})

但是,我不确定如何使用 EventEmitters 进行等效操作。换句话说,我需要等到所有这些发射器都发出了相同的事件(即“完成”),然后再执行另一个操作。

任何想法/建议如何实现这一目标?

提前致谢。

【问题讨论】:

  • 难道你不能将事件发射器包装在 Promise 中并在 Promise.all() 中使用这些 Promise 吗?
  • 你说的很对,比我原先想象的要简单。

标签: javascript node.js eventemitter


【解决方案1】:

有了promise.all,当“一切”都完成时,你就有了一个独特的信息。 当然那是里面所有的 Promise 都被 fullfiled/rejected 的时候。

如果您有一个 EventEmitter,则“一切”完成时的信息无法存储在您的 EventEmitter 逻辑中,因为它不知道该事件在何处或多久发出一次。

因此,第一个解决方案是管理外部状态“一切都已完成”,当它变为 true 时,您执行其他操作。

所以就像 promise.all 你必须把它包裹起来。

我可以想象的第二种方法是一个工厂,您可以在其中构建跟踪实例的 EventEmitters。然后这个工厂可以提供所有实例是否已被触发的信息。但是这种方法可能会在许多层面上失败:一个实例->许多调用;一个实例->没有调用; ...

只要我的 5 美分,我很乐意看到另一个解决方案

【讨论】:

    【解决方案2】:

    正如其他人所提到的,最简单的方法是返回 Promise 而不是 EventEmitter 实例。但是,根据您的问题,您可以为done 事件编写回调,如下所示:

    const names = ['Name1', 'Name2', 'Name3']
    let count = 0
    util.scaffold('Name').on('done', (paths) => {
      count += 1
      if (count < names.length) {
        // There is unfinished scaffolding
      } else {
        // All scaffolding complete
      }
    })
    

    【讨论】:

      【解决方案3】:

      我最终按照@theGleep 的建议进行操作,并将每个发射器包装在一个 Promise 中,如下所示:

      const names = ["Name1", "Name2", "Name3"] 
      const promises = names.map(name => {
           return new Promise((resolve) => {
             util.scaffold(name).on("done", paths => {
             resolve(paths)})
        })
      })
      
      // and then
      
      Promise.all(promises).then(result => {
          // more operations
      })
      

      到目前为止,它似乎在做我需要的事情,所以我现在就使用它。感谢大家的反馈:)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-03-14
        • 2016-03-23
        • 1970-01-01
        • 1970-01-01
        • 2019-12-15
        • 2015-07-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多