【问题标题】:JS Promises: Why does await have to be inside an async function?JS Promises:为什么 await 必须在异步函数中?
【发布时间】:2020-05-02 02:41:25
【问题描述】:

假设我有以下代码:

new Promise(res => res(1))
.then(val => console.log(val))

我可以像这样使用async/await 实现相同的目标:

let func = async () => {
  let val = await new Promise(res => res(1))
  console.log (val)
}
func()

我将async/await 代码放在函数中只是因为您必须在异步函数中才能使用await

我想知道的:为什么要执行此规则?只是做会有什么问题

let val = await new Promise(res => res(1))
console.log (val)

await 导致当前作用域暂停执行的原因,因此强制你将async/await 代码放在异步函数的特殊作用域内会阻止JS 暂停所有其余代码的执行?

【问题讨论】:

  • await 导致封闭函数转换为 Promise。为避免意外,该语言要求封闭函数通过声明自己 async 来声明此行为可以接受。任何函数之外的代码都没有要转换的封闭函数。即使有,也没有人会去await 它,所以执行永远不会恢复。
  • Re "await 导致封闭函数转换为 Promise":我不太理解。在上面的示例中,我认为 val 只是设置为等于一个承诺,并且封闭函数不返回任何内容。以何种方式成为承诺?
  • 你有双胞胎here吗?部分代码示例是相同的。主题以相同的方式开始。问题发布得非常及时。问题的总体主题不同,但非常相关。也许学生一起工作?只是好奇。
  • 然后,更多孪生问题herehere。这太巧合了。只是好奇。
  • 您应该建议您的同事支持这个问题,而不是自己提出问题。它将社区工作集中在一个地方,避免浪费资源。

标签: javascript asynchronous promise async-await es6-promise


【解决方案1】:

async 函数是一种不同的函数。它总是返回一个承诺。在它遇到的第一个await 处,函数执行被暂停,异步函数返回该承诺,调用者得到承诺并继续执行接下来的任何代码。

此外,async 函数会自动将其函数体包装在 try/catch 中,这样任何异常,无论是来自 await 的同步或未处理的拒绝承诺都会被 async 函数自动捕获并转化为拒绝他们自动返回的承诺。

并且,当您 return 来自 async 函数的值时,该返回值将成为它返回的承诺的解析值。

我想知道的:为什么要执行此规则?只是这样做会有什么问题......

async 函数具有许多常规函数不具备的行为,JS 解释器希望提前知道它是哪种类型的函数,以便它能够以正确的行为类型正确执行它。

我想解释器可能在编译函数体时发现它包含 await 并自动给周围的函数一个 async 行为,但这不是很明确的,只是添加或删除一个await 可以完全改变函数的工作方式。只是我的猜测,但语言设计者认为强制async 函数以这种方式声明要好得多,而不是根据函数体的内容推断其行为。

这里的大局是了解async 函数的工作方式不同:

  1. 总是返回一个承诺
  2. 自动捕获异常或被拒绝的等待,并将它们转变为拒绝
  3. 在等待时暂停函数执行
  4. 将返回值转换为它返回的承诺的解析值
  5. 将显式返回的 Promise 链接到异步返回的 Promise。

因此,如果在声明中使用 async 关键字而不是从函数体中推断出单独的行为,那么语言会更清晰、更具声明性。

【讨论】:

  • 谢谢!我有两个明确的问题:1)关于“函数执行被暂停,异步函数返回该承诺”:如果我有await new Promise(...); return new Promise(...);,那么封闭的异步函数返回第二个承诺,而不是第一个。但是你说异步函数从它命中的第一个等待中返回承诺?
  • 2) 重新“将显式返回的承诺链接到异步返回的承诺”:我不太明白。你能详细说明一下吗?
  • @gkeenley return 语句没有设置函数的返回值。它设置函数转换为的 Promise 的返回值。所以封闭函数返回一个 Promise,它本身返回另一个 Promise。然后开始链接。总的来说,我认为这个问题对于这个网站来说太宽泛了,因为它似乎需要对承诺的详细解释,而这并不是这个网站的真正目的。考虑寻找一个好的参考。
  • @gkeenley - async 函数在您点击第一个 await 时返回它自己的承诺。它不是第一次等待它返回的承诺。这是一个不同的、人为的承诺。函数的 async 承诺将使用函数的最终返回值解析,或者使用第一个具有未处理拒绝的 await 拒绝。
  • @PedroMachado - 因为在 nodejs 和浏览器中一次只运行一段 Javascript,所以该函数需要运行直到它到达 await 才能返回。
猜你喜欢
  • 2017-10-26
  • 2021-11-06
  • 2020-10-04
  • 2019-04-27
  • 2016-08-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多