Взгляните на этот код:
const { EventEmitter } = require('events');
class Trigger extends EventEmitter {
constructor () {
super();
}
run() {
setTimeout(() => {
this.emit('done');
}, 1000);
}
waitUntilDone() {
const this_ = this;
return new Promise((resolve) => {
this_.on('done', () => {
resolve();
});
})
}
}
async function main() {
const tr = new Trigger();
tr.run();
console.info('run');
// 如果监听的事件永远不会抛出,则此处程序会直接退出
await tr.waitUntilDone().then(() => console.info('Promise done'));
await tr.waitUntilDone().then(() => console.info('Promise done'));
console.info('final done');
}
main();
Программа завершится на втором await tr.waitUntilDone().t... без регистрации.
Даже второй tr.waitUntilDone() никогда не получит событие, он должен ждать вечно, не так ли?
@ Саши, он рано уходит. Pingze, const this_ = this; не нужен, так как вы используете стрелочные функции.
Итак, я полагаю, что возможно, что node.js завершится между временем срабатывания второго таймера и до того, как будет вызван ваш второй обработчик .then(), таким образом пропуская запись в журнал final done.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Если вы сбросите таймер после разрешения первого обещания, программа не выйдет, пока не будет выполнено последнее обещание.
async function main() {
const tr = new Trigger();
tr.run();
console.info('run');
await tr.waitUntilDone().then(() => {
console.info('Promise done');
// Reset the timer (this will keep the program alive)
tr.run();
});
await tr.waitUntilDone().then(() => console.info('Promise done'));
console.info('final done');
}
Вы увидите результат:
run Promise done Promise done final done
Я думаю, вы должны использовать только одну вещь: Promise или Async / Await.
1] Пример Async / Await
async function main() {
const tr = new Trigger();
console.info('run');
tr.run();
await tr.waitUntilDone();
console.info('Promise done');
tr.run();
await tr.waitUntilDone();
console.info('Promise done')
console.info('final done');
}
2] Пример обещания
function main() {
const tr = new Trigger();
console.info('run');
tr.run();
tr.waitUntilDone().then(() => console.info('Promise done'));
tr.waitUntilDone().then(() => console.info('Promise done'));
console.info('final done');
}
Ваше выражение "await tr.waitUntilDone().then(() => console.info('Promise done'));" неверно. Правильнее будет что-то вроде этого "await tr.waitUntilDone().then(() => (console.info('Promise done'), Promise.resolve()));" или "tr.waitUntilDone().then(() => console.info('Promise done'));"
Если вы хотите, чтобы ваша программа работала вечно, вы можете добавить это в начало своего кода:
(function keepalive() {
setTimeout(keepalive, 0x7FFFFFFF);
})();
По сути, пока есть ожидающее событие, среда выполнения должна оставаться открытой. Надеюсь, это будет полезно.
Имейте в виду, что node.js не дожидается выполнения обещаний перед завершением. Он действительно ждет таймеров (если вы их не
.unref()). И помните, чтоmain()немедленно возвращает обещание. Он не блокируетсяawait.