Как обещать и ждать setImmediate в Node?
Я читал о том, как не блокировать цикл событий Node. Один из способов избежать блокировки - использовать разбиение.
Я пытаюсь использовать в своем коде секционированный цикл, но не могу дождаться своего цикла. Вот упрощенная версия моего кода:
const report = {
someValue: 0
};
const runLoop = async () => {
report.someValue += 1;
// all sorts of async operations here that use async-await
if (report.someValue < 1000) {
await setImmediate(runLoop);
}
};
await runLoop();
console.log('Report is', report);
Это возвращает "Report is { someValue: 1 }", но я бы хотел, чтобы someValue было 1000.
Я предполагаю, что setImmediate не возвращает обещание, поэтому я попытался его обещать:
const setImmediatePromise = util.promisify(setImmediate);
const report = {
someValue: 0
};
const runLoop = async () => {
report.someValue += 1;
// all sorts of async operations here that use async-await
if (report.someValue < 1000) {
await setImmediatePromise(runLoop);
}
};
await runLoop();
console.log('Report is', report);
Но это также возвращает "Report is { someValue: 1 }".
Итак, как я могу дождаться этого рекурсивного "цикла" setImmediate, чтобы я сообщал console.log только после завершения всего цикла рекурсии?
1 ответ
Когда вы обещали setImmediate
, вы больше не передаете ему обратный вызов. Вместо этого вы простоawait
обещание, которое он возвращает. Затем вы выполните рекурсивный вызов:
async function runLoop() {
…
if (…) {
await setImmediatePromise();
return runLoop();
}
}
Однако, async
/await
дает вам возможность просто написать реальный цикл:
const setImmediatePromise = util.promisify(setImmediate);
const report = {
someValue: 0
};
while (report.someValue < 1000) {
report.someValue += 1;
// all sorts of synchronous operations here
await setImmediatePromise();
}
console.log('Report is', report);
(Обратите внимание на небольшую разницу в рекурсии: условие уже проверено перед первой итерацией, а setImmediate
выполняется еще раз после последней итерации. Использоватьdo
/while
или даже while(true)
+if(…)break;
если необходимо.)
Кстати, если вы уже выполняете асинхронные (неблокирующие) операции внутри цикла, нет причин для добавления дополнительных setImmediate
к нему. В руководстве рассматриваются только сложные синхронные вычисления, которые могут заблокировать цикл событий.