使用promises等待触发的事件 [英] Using promises to await triggered events
问题描述
在以下代码中, 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 await
ing 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 $ c这样的承诺$ 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屋!