如何使用 Promises 进行异步无限循环

Posted

技术标签:

【中文标题】如何使用 Promises 进行异步无限循环【英文标题】:How to have an async endless loop with Promises 【发布时间】:2017-02-15 03:02:51 【问题描述】:

我需要有一个“无尽的”while 循环,其中包含承诺。下面是一些示例代码:

let noErrorsOccured = true

while (noErrorsOccured)
    someAsyncFunction().then(() => 
        doSomething();
    ).catch((error) => 
        console.log("Error: " + error);
        noErrorsOccured = false;
    );


function someAsyncFunction() 
    return new Promise ((resolve, reject) => 
        setTimeout(() => 
            const exampleBool = doSomeCheckup();
            if (exampleBool)
                resolve();
             else 
                reject("Checkup failed");
            
        , 3000);
    );

所以这个while循环应该无限运行,除非发生错误,然后while循环应该停止。我怎样才能做到这一点?

希望您能理解我的意思,并提前致谢。

【问题讨论】:

Promise 反应(调用已完成或拒绝处理程序)在导致它们被执行的线程完成后异步执行。第一个while循环是一个无限的阻塞循环,创建了无限数量的promise,因为超时回调永远不会发生:D 可能你想要一个超时或间隔计时器在为异步检查创建的承诺在运行另一次检查之前完成后等待 3 秒? 问题是我真的不知道我的承诺需要多长时间才能解决,我只使用setTimeout() 来澄清我的例子。但是 Felix Kling 的解决方案效果很好,所以不需要其他解决方案,但无论如何谢谢 :) 【参考方案1】:

我怎样才能做到这一点?

没有阻塞循环,因为 Promise 无法解决。你可以了解更多关于javascript's event loop on MDN的信息。

相反,当 promise 解决后再次调用该函数:

Promise.resolve().then(function resolver() 
    return someAsyncFunction()
    .then(doSomething)
    .then(resolver);
).catch((error) => 
    console.log("Error: " + error);
);

【讨论】:

啊我一开始搞砸了。没有足够仔细地查看 OP 的原始代码 @kingdango:嗯?您是否也厌倦了try catch() s 中的catch 不会重新抛出错误?错误处理是catch 子句的重点... 是的,通常情况下。堆栈上的大多数调用都无法充分“处理”异常,因为外部调用具有相关的后果。您唯一应该尝试捕获堆栈的时间是当您需要记录在错误返回堆栈时不可用的本地范围信息时,在这种情况下您应该记录并抛出,以便外部调用有机会决定如何处理异常。显然有一些场景,批处理操作是最好的例子,其中一个失败的调用不应该阻止其他调用的执行,在这种情况下你“处理异常”并继续前进。 永远运行这个对内存有什么影响? 这个答案有内存泄漏:github.com/nodejs/node/issues/6673你会用完堆【参考方案2】:

这在 NodeJS 中对我有用(基于此处的讨论:https://github.com/nodejs/node/issues/6673):

async function run()
  // Do some asynchronous stuff here, e.g.
  await new Promise(resolve => setTimeout(resolve, 1000));


(function loop()
   Promise.resolve()
     .then(async () => await run())
     .catch(e => console.error(e))
     .then(process.nextTick(loop));
)();

【讨论】:

以上是关于如何使用 Promises 进行异步无限循环的主要内容,如果未能解决你的问题,请参考以下文章

使用 setInterval() 的无限异步循环 [重复]

为啥这个异步函数无限循环?

异步、等待和无限循环

为啥计算内部的异步会产生无限循环(vue)?

Angular 2 - 异步管道中的无限循环

Angular 11异步验证器触发真实响应的无限循环请求