JS承诺。为什么 await 一定要放在一个异步函数里面?

问题描述 投票:0回答:1

假设我有以下代码。

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 在async函数的特殊作用域内的代码可以防止JS暂停执行你所有其他的代码?

javascript asynchronous promise async-await es6-promise
1个回答
1
投票

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

此外, async 函数会自动将其函数体包裹在一个 try/catch 以便任何异常,无论是同步的还是未处理的拒绝来自于一个 await 会自动被 async 函数,并变成了拒绝它们自动返回的承诺。

而且,当你 return 中的一个值 async 函数,该返回值就成为它返回的承诺的解析值。

我想知道什么?为什么要执行这个规则?如果只做这个函数,会有什么问题?

async 函数有一些行为是普通函数所没有的,JS解释器希望提前知道它是哪种类型的函数,这样就可以用正确的行为类型正确执行它。

我想可能是解释器在编译函数体时发现它包含了一个 await 并自动赋予周边函数一个 async 行为,但这不是很好的声明,只是简单地增加或删除一个 await 可以完全改变函数的工作方式。 这只是我的猜测,但语言设计者们决定最好强行使用一个 async 函数,而不是根据函数体的内容来推断其行为。

这里的大局是要理解一个 async 函数只是工作方式不同。

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

而且,如果在声明中以 async 关键字,而不是从函数体中推断出来的。

© www.soinside.com 2019 - 2024. All rights reserved.