【发布时间】:2020-01-14 06:56:58
【问题描述】:
我试图弄清楚异步代码在 Javascript 中是如何工作的。现在,我了解到JS中实际上有一个单线程执行队列中的作业,并且只有在当前作业完成后才能开始执行下一个作业(即如果所有同步代码或异步函数都已完成) .
现在,令人困惑的部分是实际上算作异步函数的部分 - 哪些实际被放入队列中的单独作业中,哪些没有。
首先,我们有函数的async 关键字。那么这是否意味着这些功能将被放入队列中的单独作业中并在将来的某个地方执行?好吧,实际上答案是NO。但请耐心等待,我将解释。
据我了解,理论上,JS 线程应该首先执行所有同步代码,直到它完成,同时延迟所有异步函数、承诺和回调的执行,将它们作为作业放置到末尾队列。然后,一旦所有同步代码完成,它将开始执行所有那些堆积起来的工作。
所以如果我有以下代码:
async function asyncFunc() {
console.log("executing async function");
}
console.log("starting sync code");
asyncFunc().then(() => {
console.log("executing callback of async function")
});
console.log("sync code completed");
那么理论上应该先执行所有同步代码,然后才开始执行异步函数,然后是回调:
starting sync code
sync code completed
executing async function
executing callback of async function
但实际情况不同!实际上,它实际上同步地 执行异步函数,以及其余的同步代码。唯一真正放入作业队列的是异步函数的回调:
starting sync code
executing async function
sync code completed
executing callback of async function
那是什么意思? async 函数实际上是一个谎言?看起来是这样,因为它们实际上是 正常的同步函数,您可以碰巧将 async 回调附加到它们。
现在,我知道async 实际上是返回Promise 的函数的语法糖,例如:
async function asyncFunc() {
console.log("executing async function");
}
是语法糖:
function asyncFunc() {
return new Promise((resolve) => {
console.log("executing async function");
resolve();
});
}
但我的观点仍然存在。您传递给 Promise 的所谓异步函数实际上是同步执行的。好吧,从技术上讲,Promise 对象并不意味着它将异步执行,但 async 关键字却可以!所以这是彻头彻尾的虚假信息,它让你相信它是异步的,而事实证明并非如此。
【问题讨论】:
-
你的
asyncFunc实际上是function asyncFunc() { console.log("executing async function"); return new Promise(); }的同义词 所以没有谎言 - 它只是没有按照你的想法做。 -
同步部分和异步功能“并行”运行。您可以尝试添加延迟,然后异步输出将再次在同步输出结束后。
-
如果你编写了一个从不调用
await的async函数,那么是的,这并不奇怪。async/await语法实际上就是这样:使用纯 Promise 对象管理.then()回调代码链问题的语法便利。 -
您误解了
async/await语法的意图。 -
真正将
async视为一种“类型”声明的最佳方式,它告诉JavaScript“此函数返回一个或多个Promise 对象”。然后解析器可以将该函数的代码构建为 generator 函数,每个内部await表达式实际上意味着另一个 Promise 的yield。
标签: javascript node.js asynchronous async-await