异步/等待:异步嵌套函数是不是需要自动等待上一级?

Posted

技术标签:

【中文标题】异步/等待:异步嵌套函数是不是需要自动等待上一级?【英文标题】:Async/await: do async nested functions automatically need to be awaited a level above?异步/等待:异步嵌套函数是否需要自动等待上一级? 【发布时间】:2020-01-28 14:38:39 【问题描述】:

我有几个关于 async/await 如何跨级别流动的问题。一些示例代码:

class Auth
  async validateJwt()  // A
    const result = await fetch(...) // #1
    return await result.json(); // #1.5
  

  async createJwtOrValidateExisting()  // B
    const token = await validateJwt(); // #2
    return token.data;
  


const auth = new Auth();

// React.js top level component
const App = props => 

  useEffect(() =>  // C
    const tokenData = auth.createJwtOrValidateExisting(); // #3    
  

我需要在第 2 步和第 3 步都等待吗?

如果是这样,我想我也需要在 C 行添加一个 async 关键字。

我知道 await 会暂停执行,这在 fetch() 和 .json() 步骤中是必需的。第一种方法很直观。

但是当你在第 2 步等待时,我相信这也需要更高级别函数上的 async 关键字,这意味着必须从它返回一个承诺。这似乎不合适,因为 .json() 步骤已在步骤 1.5 中处理/解决。

如果这种解释不正确,并且我在步骤 B / #2 上确实需要 async/await,这意味着我还必须将 useEffect 回调转换为异步函数。

对以上这些关键字的正确用法的任何解释都会有很大帮助,谢谢。

【问题讨论】:

简短的回答是……是的。 async 函数总是返回一个承诺 【参考方案1】:

我需要在第 2 步和第 3 步都等待吗?

对于#2,是的。 validateJwt 是一个 async 函数。如果你在没有await 的情况下调用它,你会得到一个承诺。如果您使用 await 调用它,您将获得该承诺的已解决值。

对于#3useEffect 不是异步函数,所以你必须使用then 来处理createJwtOrValidateExisting 返回的promise。或者,您可以将 useEffect 设为异步函数,并在 createJwtOrValidateExisting 上使用 await

另外,在#1.5 中,return await result.json() 上的await 不是必需的。 response.json() 返回一个承诺,您可以立即从异步函数中返回它。见https://eslint.org/docs/rules/no-return-await

这应该是:

class Auth
  async validateJwt() 
    const result = await fetch(...)
    return result.json()
  

  async createJwtOrValidateExisting() 
    const token = await validateJwt()
    return token.data
  


const auth = new Auth();

const App = props => 

  async useEffect(() => 
    const tokenData = await auth.createJwtOrValidateExisting()
  

经验法则是异步函数只是一个返回承诺的函数。如果您想在不使用then 的情况下提取其值,则使函数异步,并在该承诺上使用await

【讨论】:

以上是关于异步/等待:异步嵌套函数是不是需要自动等待上一级?的主要内容,如果未能解决你的问题,请参考以下文章

JS的Promise兄弟

等待先前的异步功能完成[重复]

在自定义承诺上使用异步等待

在自定义承诺上使用异步等待

useEffect 等待异步函数的结果

ES7 - 如何停止(剪切)异步/等待链接