我一直在阅读有关如何不阻止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);

这将返回“Report is {someValue:1}”,但我希望someValue为1000。

我猜setImmediate不会返回 promise ,所以我尝试了使它成问题:
    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报告?

最佳答案

promise 了setImmediate后,您将不再向其传递回调。相反,您只需await它返回的 promise 。然后,您将进行递归调用:

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仅处理会阻塞事件循环的复杂同步计算。

10-07 21:12