I've been reading about how to not block Node's event loop. One way to avoid blocking is to use partitioning.
I'm trying to use a partitioned loop in my code, but I cannot seem to await for my loop. Here's a simplified version of my code:
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);
This returns "Report is { someValue: 1 }", but I'd want someValue to be 1000.
I'm guessing setImmediate doesn't return a promise, so I've tried promisifying it:
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);
But this also returns "Report is { someValue: 1 }".
So, how can I await for this recursive setImmediate "loop" so that I console.log report only after the entire recursion cycle is finished?
When you have promisified setImmediate
, you no longer pass a callback to it. Instead, you just await
the promise it returns. Then afterwards you'd do the recursive call:
async function runLoop() {
…
if (…) {
await setImmediatePromise();
return runLoop();
}
}
However, async
/await
gives you the capability to just write an actual loop:
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);
(Notice the slight difference to the recursion: the condition is already checked before the first iteration, and the setImmediate
runs once more after the last iteration. Use do
/while
or even while(true)
+if(…)break;
if necessary.)
Btw, if you are already doing asynchronous (non-blocking) operations inside the loop, there is no reason to add an extra setImmediate
to it. The guide only deals with complex synchronous calculations that would block the event loop.