繁体   English   中英

等待异步 function 会暂停执行,即使 function 立即返回

[英]awaiting an async function pauses execution even when the function immediately returns

我最近遇到了一个问题,基本上可以归结为以下代码片段:

 let a = 0; async function f1(){ // doesn't do anything most of the time } async function f2(){ a++; await f1(); console.log(a); } for (let i=0;i<3;i++){ f2(); }

我有一个异步 function f1可能会执行一些异步操作,但大多数时候不执行任何操作。 它在另一个 function f2中被调用并等待,它可能会被快速调用而无需等待前一个调用完成,例如在本例中的 for 循环中。

在此示例中,我希望 output 为 1、2 和 3; 由于f1立即返回,等待它不应该暂停f2的执行,因此代码应该同步运行,就好像不涉及任何 async-await 一样。 但是,当我在 chrome 或 firefox 中对此进行测试时,output 始终为 3、3 和 3,这表明await f1()暂停了f2的执行并继续执行 for 循环。

同样,这也会导致我尝试编写的脚本出现逻辑错误。

这种行为的原因是什么? 有没有办法解决这个问题?

来自 Promise.prototype.then 上的mdn web 文档:

一旦 Promise 被满足或拒绝,相应的处理程序 function(onFulfilled 或 onRejected)将被异步调用(在当前线程循环中调度)。

因此,任何依赖于 Promise 及其then方法的代码也将异步运行,即使这些 Promise 已经像您的f1方法那样被解析。

您可以通过使用自定义thenable 对象在某种程度上解决此问题:

 let a = 0; function f1(){ return {then:(onResolve)=>{ onResolve(); // resolves immediately }}; } async function f2(){ a++; f1().then(()=>{ console.log(a); }); } for (let i=0;i<3;i++){ f2(); }

但是,从异步 function 中返回它们或等待它们将再次将它们转换为正常的 Promise,从而导致代码像以前一样异步运行。

所以,如果你真的想使用 async/await,我认为不可能避免这种行为; 一个更好的主意可能是以不会引起问题的方式重写您的代码。

你需要await f2(); 在循环中获得预期的 output 的1, 2, 3 像这样:

(async function() {
    for (let i=0;i<3;i++){
        await f2();
    }
})();

为什么? 因为在原始代码中,当您不await f2();

  1. f2() 被调用(迭代 1)
  2. a 递增(迭代 1)
  3. f1 的代码已排队(迭代 1)
  4. f2() 被调用(迭代 2)
  5. a 递增(迭代 2)
  6. f1 的代码已排队(迭代 2)
  7. f2() 被调用(迭代 3)
  8. a 递增(迭代 3)
  9. f1 的代码已排队(迭代 3)
  10. a 现在是 3
  11. 现在,排队的代码在其完整时被处理(以任何顺序)
  12. 由于此时 a 的值为 3,因此成功等待 f1 的 3 个排队的 f2 调用中的任何一个都将在 f2 中打印 3

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM