如何在 Node 中承诺和等待 setImmediate?

How to promisify and await for setImmediate in Node?

我一直在阅读如何不阻塞 Node 的事件循环。避免阻塞的一种方法是使用 partitioning.

我正在尝试在我的代码中使用分区循环,但我似乎无法等待我的循环。这是我的代码的简化版本:

    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);

这个 returns "Report is { someValue: 1 }",但我希望 someValue 为 1000。

我猜 setImmediate 没有 return 承诺,所以我试过承诺它:

    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);

但这也 returns "Report is { someValue: 1 }".

那么,我怎样才能等待这个递归 setImmediate "loop" 以便我 console.log 仅在整个递归周期完成后才报告?

当您承诺 setImmediate 后,您不再向其传递回调。相反,您只是 await 承诺它 returns。然后你会做递归调用:

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; 如果需要的话。)

顺便说一句,如果您已经在循环内执行异步(非阻塞)操作,则没有理由向其添加额外的 setImmediateguide 仅处理复杂的 同步 计算,这些计算会 阻塞 事件循环。