【问题标题】:What's the difference between await an async function and directly calling an async function [duplicate]等待异步函数和直接调用异步函数有什么区别[重复]
【发布时间】:2021-11-18 23:34:17
【问题描述】:

我最近读了一本关于异步和等待模式的书,其中有一章是关于延迟等待或早期初始化的。书上说:

这允许结构提前开始异步处理,但只在需要结果时停止。

const wait = (ms) => new Promise(res => setTimeout(res, ms));

const fn = async () => {
  console.log("starting");
  await wait(100); // I suppose await should pause the execution
  console.log("end");
}

(async () => {
  const fnPromise = fn();
  console.log("after"); // However after is printed brfore end
  await fnPromise;
})();

如果我稍微修改一下代码

(async () => {
  await fn(); // looks like the inner await only takes effect when I await an async function
  console.log("after"); // after is printed after end
})();

我的意思是await 一个异步函数和直接调用它有什么区别。关于何时使用 await 或何时不使用 await 异步函数是否有任何最佳实践。 await 是否真正阻止执行,尤其是与计时器结合使用。 感谢@asynts 的snippet,我会发在这里

let samples = 100 * 1000 * 1000;
let chunk = 100000;

async function run() {
    let sum = 0.0;
    for(let i=0; i<samples; i++) {
        sum += Math.random();

        if (i % chunk === 0) {
            console.log("finished chunk")
            // wait for the next tick
            await new Promise(res => setTimeout(res, 0));
            // If await truly blocks the execution, rest of the code are all waiting? 
            // If await doesn't block the execution, what's the point to await here
        }
    }

    let mean = sum / samples;
    console.log("finished computation", mean);
}

setTimeout(run, 0);

【问题讨论】:

  • 据我了解,await 一个异步函数会导致 inner await 阻塞执行,但这是否意味着我们需要 await 所有异步函数一直向上?
  • 我建议你,使用调试器,以查看异步函数的控制流程...
  • 这里的关键是await 只暂停了包含函数的执行,而不是它之后的代码。在您点击 await` 时,该函数被挂起,它立即返回一个 promise,函数调用后的代码接收到返回的 promise 并继续执行。由调用代码对返回的 Promise 做一些有用的事情。
  • @jfriend00 所以如果你想确保外部await之后的代码被挂起,使用外部await。或者如果你想让代码流动,不要使用外部await(这意味着忽略异步函数返回的承诺,尽管包含函数仍然会由于内部await而暂停)
  • 代码将在某种程度上流动。否则,您将陷入僵局,并且不会发生任何事件,甚至不会发生将完成异步操作的事件。如果这是调用者的愿望(调用者想要等待完成),您可以在外层使用await。否则,我真的不明白你想要完成什么。您根据您的编程目标构建代码 - 它们不是适用于所有情况的通用结构。而且,您应该始终使用.catch() 或在await 周围的`try/catch` 处理被拒绝的承诺。

标签: javascript asynchronous async-await promise timer


【解决方案1】:

await 一个异步函数和直接调用它有什么区别。

嗯,你已经在前两个 sn-ps 中清楚地观察到了差异。

关于何时使用 await 或何时不使用 await 异步函数是否有任何最佳实践?

是的:总是立即做。不要让诺言围绕着 un-awaited(就像你的 fnPromise 变量一样)。

不这样做不一定是错的,但会增加出错的可能性:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多