使用promises等待触发的事件

13 javascript promise async-await

在下面的代码中,thing是一个我无法控制的外部对象; 我无法改变事件系统的thing工作方式.当fn调用时,我们返回一个promise,其执行程序侦听一个事件,然后开始等待一系列函数,最终导致该事件被触发:

function fn() {

  return new Promise(async function(resolve, reject) {

      // This handler must be attached before `c` is called
      thing.once('myEvent', function(e) {
        resolve(e.data); // done
      });

      // The order of these functions calls is important,
      // and they may produce errors that need to be handled.
      await a();
      await b();
      await c(); // this causes myEvent

  });

}
Run Code Online (Sandbox Code Playgroud)

这工作正常,但我被告知这是一个承诺反模式,我应该做fn一个async功能.我该怎么做?如果我创建了fn一个async函数,那么我如何e.data从事件处理程序中解析?

编辑:

我接受了Bergi的答案,因为它有助于解释反模式以及它如何应用于这种情况.话虽如此,我认为上面的代码更具可读性并且明确地显示了正在发生的事情,所以我将保持原样.这不是noob谴责最佳实践,只是对于我的用例,遵循规则使事情变得比他们需要的更复杂.当然,这让我对某些问题持开放态度,但我必须忍受这一点,直到我找到更好的方法来做到这一点.

Ber*_*rgi 19

不要awaitPromise构造函数中做任何事情- 你应该在那里做异步回调的promisification:

async function fn() {
  await a();
  await b();
  await c(); // this causes myEvent
  return new Promise(function(resolve, reject) {
    thing.once('myEvent', function(e) {
      resolve(e.data); // done
    });
  });
}
Run Code Online (Sandbox Code Playgroud)

启动进程最终导致事件发生的事情通常Promise也在执行程序回调内部调用(以捕获同步异常),但通常它不会像c函数那样返回一个promise .

也许这表达了更好的意图:

async function fn() {
  await a();
  await b();
  const {data} = await new Promise(resolve => {
    thing.once('myEvent', resolve);
    thing.c(); // this causes myEvent
  });
  return data;
}
Run Code Online (Sandbox Code Playgroud)

当然,这假设您只需要在调用其他事件时开始收听事件.如果您希望事件在此之前触发,那么您基本上会进行并行执行的竞赛 - 我建议Promise.all在这种情况下使用:

async function fn() {
  await a();
  await b();
  const [{data}, cResult] = await Promise.all([
    new Promise(resolve => thing.once('myEvent', resolve)),
    c()
  ]);
  return data;
}
Run Code Online (Sandbox Code Playgroud)