使用promises等待触发的事件 [英] Using promises to await triggered events

查看:106
本文介绍了使用promises等待触发的事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In the following code, thing is an external object that I don't control; I can't change how the event system of thing works. When fn is called, we return a promise whose executor listens to an event and then begins awaiting a series of functions which eventually result in that event being triggered:

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

  });

}

这样可行,但我被告知这是一个承诺反模式,我应该 fn 一个 async 函数。我该怎么做?如果我使用 fn 一个 async 函数,那么我该如何解析 e.data 来自事件处理程序?

This works fine, but I've been told that this is a promise anti-pattern and that I should make fn an async function. How would I do this? If I made fn an async function, then how could I resolve e.data from within the event handler?

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

I've accepted Bergi's answer because it is helpful in explaining the anti-pattern and how it applies to this scenario. Having said that, I think the code above is more readable and shows explicitly what's happening so I'm going to keep it as is. This isn't the noob denouncing the best practices, it's just that for my use-case, following the rules makes things more complicated than they need to be. Of course, this leaves me open to certain problems, but I'll just have to live with that until I find a better way to do this.

推荐答案

Don'在 Promise 构造函数中执行任何等待 - 你应该在那里进行异步回调的默认:

Don't do any awaiting inside the Promise constructor - you only should do the promisification of the asynchronous callback in there:

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
    });
  });
}

启动流程最终导致事件发生的事情通常是在 Promise 执行者回调中调用(以捕获同步异常),但通常它不会返回像 c 功能确实。

The thing that starts the process which eventually causes the event to be emitted is usually called inside the Promise executor callback as well (to catch synchronous exceptions), but usually it doesn't return a promise like your c function does.

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

Maybe this expresses the intent better:

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

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

Of course this assumes that you only need to start listening to the event when you've called the other ones. If you expect the event to fire before that, you essentially have a race with parallel execution - I'd recommend to use Promise.all in that case:

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

这篇关于使用promises等待触发的事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆