【问题标题】:How does javascript async/await actually work?javascript async/await 是如何工作的?
【发布时间】:2021-12-18 04:42:59
【问题描述】:

我有一些使用 javascript async/await 的代码:

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function fun1()
{
     console.log("dosomething1");
     await sleep(6000);
     console.log("dosomething2");
     return "returnfromfun1";
}
console.log(fun1());
console.log("hello");

根据official document关于async/await:

一个异步函数可以包含一个等待表达式来暂停 执行异步函数并等待传递的 Promise 解决,然后恢复异步函数的执行和 返回解析后的值。

我希望得到以下输出:

dosomething1
//wait for 6 seconds
dosomething2
Promise { <state>: "fulfilled", <value>: "returnfromfun1" }
hello

但实际输出是:

dosomething1
Promise { <state>: "pending" }
hello
//wait for 6 seconds
dosomething2

似乎 fun1 在“等待”行返回。是我误解了官方文档中的描述吗?看来我从来没有得到 fun1("returnfromfun1") 的返回值。

【问题讨论】:

  • fun1 是异步的,因此只需使用 console.log(fun1()); 调用它就不会等待它解决 - 无论是 await 它还是调用 .then
  • “根据官方文档”——这是一个任何人都可以编辑的 wiki,而不是官方文档。官方文档在这里:ecma-international.org/ecma-262/9.0/…
  • 异步函数返回承诺。调用该函数会立即同步地返回未解决的承诺。可以在 .then() 中检索承诺的结果,例如 fun1.then((result) =&gt; {}) 或通过等待它,例如 var result = await fun1()
  • 啊哈,那个文件太官方了,看一眼就头疼:)
  • @JonasWilms 这么想,这几乎是一回事 - var result = foo();(在另一个问题中)不等待异步操作完成,就像这里的 console.log(fun1()); 不等待异步动作完成,虽然我猜还有stackoverflow.com/questions/23667086/…

标签: javascript asynchronous async-await


【解决方案1】:

您必须以稍微不同的方式阅读引用的部分:

async 函数可以包含一个 await 表达式,用于暂停 async 函数的执行

只是异步函数本身暂停执行,然后调用它的函数继续执行。

如果你想到一个同步调用堆栈,会发生什么是异步函数上下文被弹出,并存储在其他地方:

 stack: [init] -> [async] fun1 -> sleep -> setTimeout
  // The promise gets returned from sleep
 stack: [init] -> [async] fun1
 // The async function gets popped of
 stack: [init]
 hidden: [async] fun1
 // synchronous execution ends
 stack: -
 hidden: [async] fun1
 // the timer triggers, the promise gets resolved
 stack: setTimeout callback
 hidden: [async] fun1
 // synchronous execution ends
 stack: -
 hidden: [async] fun1
 // the promise resolves, the async fun1 context gets moved onto the stack
 stack: [async] fun1

fun1 似乎在“等待”行返回

是的,没错。在那一刻它返回一个promise,当异步函数返回时(在它继续执行之后)解析。

而且似乎我从来没有得到 fun1("returnfromfun1") 的返回值。

当promise解决时你可以得到它:

  fun1().then(result => console.log(result));

【讨论】:

  • @JonasWilms,你的意思是从 fun1 在 await 返回的 Promise 对象是在 sleep 函数中创建的吗?您能否指出一个权威文档,声明 await 将从当前异步函数返回,并带有由 await 关键字后面的函数创建的 Promise 对象?
  • @william no, fun1 将在内部创建一个承诺并返回它。唯一的“权威文件”是规范,当然我可以引用相关部分,但我认为这对您目前的理解阶段没有帮助(规范真的非常难以阅读)
  • 连promise都不是sleep创造的,它一定是那个的副本吧?因为承诺在 6 秒后得到解决。
  • 没有。当sleep() 返回的promise 解析时,异步函数继续执行returns,并在内部解析该内部promise。所以它们不是彼此的“副本”。
  • 现在感觉好多了。非常感谢,乔纳斯威尔姆斯!
猜你喜欢
  • 1970-01-01
  • 2018-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-04
  • 1970-01-01
  • 2020-03-09
相关资源
最近更新 更多