我实际上是第一次深入了解 asyc/await 部分,所以我很难理解它。
我知道 async wait 用于使函数以异步方式运行,但是如何,因为根据定义,“await”关键字会暂停函数的执行,直到承诺得到解决,然后执行中的剩余代码功能。这不是同步行为吗,因为事情正在按应有的顺序执行?
如果我有什么地方错了,请随时帮助我摆脱困惑。
都不是。
async
和await
关键字是管理承诺的工具。
Promise 是一种管理异步代码的工具。
如果将函数标记为
async
那么:
await
如果您在 Promise 的左侧使用
await
,则包含函数将进入休眠状态,直到 Promise 解决。异步函数外部的执行将在休眠时继续(即不会停止)。
这使您可以使用看起来适用于同步代码的语法来处理异步代码。
它不会使同步操作异步,反之亦然。
这不是同步行为吗,因为事情正在按应有的顺序执行?
这取决于我们如何定义术语同步和异步。它们在 JavaScript 世界中具有非常特定的含义。首先,这些术语是“相对”术语,即它们需要一个上下文:我们可以说代码是相对于当前正在运行的某些代码同步执行的。如果我们说代码是相对于当前任务异步执行的,那么这意味着它在调用堆栈为空之前不会执行,并且它是由某个作业队列中的作业触发的。 但是当一段异步代码开始运行时,我们开始以该执行为参考点进行讨论,我们可以再次谈论它的某些部分是同步执行的,而其他部分可能仍然是异步执行的,再次涉及a中的作业作业队列。 简而言之,当当前执行的代码(参考点)和我们标记为“异步”的代码执行之间,调用堆栈为空时,我们就谈到异步。
await
我不会称之为“停止”。对于函数的调用者来说,函数已同步执行到(并包括)停止
await
表达式。然后,该函数向调用者返回(承诺):调用者的代码执行将像在任何其他函数调用之后一样继续执行。没有真正的
。相反,异步函数的执行上下文将被保存以供以后继续。
同样,作为异步函数同步执行的一部分,await
运算符评估其操作数,如果它不是 thenable(如 Promise),则将其包装到 Promise 中。然后函数返回。因此,从调用者的角度来看,操作数也是同步计算的。
当 Promise 解决时,作业将被放入微任务队列(Promise 作业队列)中。当调用代码(同步代码)执行运行直到调用堆栈为空时,JavaScript 引擎将检查其队列。如果它发现微任务队列中已经存在该 Promise 作业,它将执行它。这将恢复保存的异步函数的执行上下文,并且代码可以从该点开始继续执行。
如果遇到另一个
await
,则计算其操作数,这次异步函数返回到作业处理程序(而不是您的代码),使调用堆栈为空。在某些时候,等待的承诺可能会解决,这将再次将作业放入微任务队列中......等等。