【问题标题】:code inside async function executes before the code that follows itasync 函数中的代码在其后面的代码之前执行
【发布时间】:2018-05-29 22:21:56
【问题描述】:

我目前正在探索 javascript 中 async/await 的概念。我知道 async 函数返回一个应该在未来解决的承诺,并且它不会阻止代码的自然执行。这里我有一个代码我写来测试javascript的异步执行。

console.log("1")
async function asyncFunc(){
  for(i=0;i<10000000;i++){
  }
  console.log("3")
}
asyncFunc().then(()=>{console.log('4')});
console.log("2");

我除了代码将按以下方式执行:

第一个 console.log() 打印 1

其次调用异步函数。由于异步代码是非阻塞的,最后一个 console.log() 将执行并因此在控制台中打印 2。

async 函数中的 console.log() 将被执行并在控制台中打印 3。

最后,promise 将被解析,then 中的 console.log() 将被执行并打印 4。

如此预期的输出:1,2,3,4

但实际上我得到的输出是 1,3,2,4。

为什么它会这样,而不是我预期的方式

【问题讨论】:

  • 不幸的是,aync 关键字实际上并没有使函数中的代码异步。
  • 如果要强制函数异步运行,则在函数的第一行添加await Promise.resolve()

标签: javascript asynchronous async-await


【解决方案1】:

该函数在完成运行之前不会返回一个 Promise(除非你在其中 await 另一个 Promise)。

循环运行(阻塞一切),然后评估console.log("3"),然后返回一个promise。

调用函数继续运行(记录 2)。

最后,释放事件循环并调用传递给then的函数。

将函数标记为异步不会将其中的同步代码转换为异步代码。

【讨论】:

  • 声明它是异步的,我希望它是异步的。如果它仍然阻塞,那有什么意义呢?
  • @AL-zami — 它为您处理异步代码提供了更好的语法(因为您可以使用处理返回而不是回调的语法)。
  • 不幸的是,您的最后评论使它更难掌握:(
  • 查看 MDN 页面以了解异步。它有例子。
  • 异步意味着它可以异步运行,但不会使其异步。异步函数内部的“等待”是使其异步的原因。 asyncFunc 内部没有“等待”,所以它不是真正的异步
【解决方案2】:

这里的答案晚了,昆汀是完全正确的,但有时绘制这些东西很有帮助。让我们看看非常简单的async函数:

async function foo() {
    console.log("a");
    await something();
    console.log("b");
    return 42;
}

这个函数有两个部分:

  • 同步部分:直到(但不包括)第一个awaitreturn(或者如果它刚刚结束)的所有内容。所以在上面,这是console.log("a"); 和对something 的调用(但不是等待其结果的位)。
  • 异步部分:第一个 await 之后的任何内容。

如果我们用明确的承诺重写那个函数,它看起来像这样(挥手离开细节)

function foo() {
    console.log("a");
    return something().then(() => {
        console.log("b");
        return 42;
    });
}

所以看看你的功能:

async function asyncFunc(){
  for(i=0;i<10000000;i++){
  }
  console.log("3")
}

...我们可以看到函数中所有的代码都在它的初始同步部分,它返回的promise会被undefined解析。

那么为什么async 函数有同步部分?出于同样的原因,您传递给new Promise 的执行器函数同步运行:因此它可以立即开始其工作。

假设我们想要在 fetch 周围做一个 async 包装器,我们期望在其中得到 JSON 响应:

async function fetchJSON(...args) {
    const response = fetch(...args);
    return response.json();
};

如果它没有同步部分(对fetch(...args) 的调用),它就永远不会做任何事情,它的承诺也永远不会兑现。

【讨论】:

    猜你喜欢
    • 2018-05-27
    • 2022-11-28
    • 1970-01-01
    • 1970-01-01
    • 2016-07-07
    • 1970-01-01
    • 2021-08-03
    • 1970-01-01
    • 2019-02-07
    相关资源
    最近更新 更多