Ответ 1
Не делайте никаких await
внутри конструктора Promise
- вам нужно только выполнить обещание асинхронного обратного вызова:
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
.
Может быть, это выражает намерение лучше:
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
в этом случае:
async function fn() {
await a();
await b();
const [{data}, cResult] = await Promise.all([
new Promise(resolve => thing.once('myEvent', resolve)),
c()
]);
return data;
}
Если у вас есть узел v11.13.0 или выше, вы можете использовать метод events.once
чтобы вам не нужно было создавать обещание самостоятельно - он также правильно обрабатывает события ошибок:
import { once } from 'events';
async function fn () {
await a()
await b()
await c()
await once(thing, 'myEvent')
}