【问题标题】:Why do I need to use async/await twice to make this Non-blocking? [duplicate]为什么我需要使用 async/await 两次来使这个非阻塞? [复制]
【发布时间】:2020-01-31 21:29:24
【问题描述】:

我有两个函数,第一个是主函数,它有 switch 语句调用第二个是异步的。如果我的第二个功能是异步的,那不是非阻塞的吗?我是否仍然必须使第一个异步以使其成为非阻塞,如果是,为什么?

示例

exports.funcOne = async (theParam) => { // async ??
    switch (theParam) {
        case 'hey':
            return await funcTwo()
       default:
            ...
    }
}

const funcTwo = async () => {
   await axios.get...
}

【问题讨论】:

  • async/await 不会改变阻塞和阻塞,它只是将它推到下一个滴答声。
  • @Jonas Wilms 我不认为这与您标记的问题重复。这个问题是关于 Async / Await 的一般问题。这是在询问必须在嵌套函数中使用两组异步等待
  • 我已经添加了针对您的问题的答案。
  • 这个问题不是完全重复的,但是那里的答案会在这里回答你的问题。

标签: javascript node.js


【解决方案1】:

一般情况下,所有包含await的函数都必须是async

如果我们认为该规则不存在,并且您可以在同步函数中等待异步结果,则该规则可能更有意义。

首先,我们需要了解关于函数的一件重要事情:

它们必须运行到完成,或者换句话说:常规函数运行到return 并且没有其他代码可以同时运行

如果我们可以在非异步函数中await,这意味着我们将阻止执行,直到等待的承诺解决,因为在此期间没有其他代码可以运行。由于解析promise的代码也无法运行,我们造成了死锁。

async functions 只运行到完成,直到他们到达await。因此,当axios.get(...) 被调用时,会从它同步返回一个promise,funcTwo halts execution,返回一个promise 本身,因此funcOne 也会停止执行(这可能是因为它是async)。然后引擎可以继续处理其他事情,当底层请求完成时,promise 解决了,funcTwo 继续执行解决了它返回的 promise,funcOne 继续执行并也解决了返回的 promise。

如果我的第二个函数是异步的,那不是非阻塞的吗?

这真的取决于你对非阻塞的定义。一般来说,每一个执行的 JS 代码都会“阻塞线程”(因为一次只能执行一个函数),但由于大多数任务非常小,你不会注意到阻塞。

asnyc function 也处于阻塞状态,只要它不会因为承诺解决而停止。则处于非阻塞等待状态。

异步任务(例如执行网络请求)也不会阻塞,因为它们由引擎处理(卸载到其他线程或硬件等)。

【讨论】:

    【解决方案2】:

    调用 AsyncFunction 会返回一个 Promise。正如 Eric 所说,您可以在 funcTwo 中返回 Promise,它不需要是 AsyncFunction,因为它是安全的,并且位于 functionOne 线程中。所以如果你在functionTwo中返回Promise,Promise“axios.get...”的结果将在functionOne中的“return await funcTwo()”中解析。

    【讨论】:

      【解决方案3】:

      第二个函数可以只返回承诺:

      exports.funcOne = async (theParam) => { // async ??
          switch (theParam) {
              case 'hey':
                  const myData = await funcTwo();
                  console.log("response from request : ", myData);
                  //do something with data
             default:
                  ...
          }
      }
      
          const funcTwo = () => {
             //axios.get is a promise, so is the return type for funcTwo
             return axios.get...
          }
      
      

      【讨论】:

      • 所以只要 funcOne 是异步的 funcTwo 就不必是因为它已经返回了一个承诺并因此做了一个异步的事情?
      • 这是一个常见的错误,忘记返回承诺,如果这样“void”是返回,所以第一个等待不要等待!。有时我们忘记了 async await 是一个漂亮的解决方案,这要归功于 Promise,并且由于 javascript 不是强类型的,如果没有执行 return 语句,它允许隐式返回“void”的东西。
      • 我还需要在funcOne里面返回吗?
      • 由你决定:funcOne 的返回类型是什么?你已经在等待functTwo的结果,所以我想你现在想要处理响应(也许将json从你的调用转换为数据?无论如何,承诺现在已经完成,所以不需要将它发送到另一个级别。所以在我看来要清楚,不,你只需要对返回的值做一些事情,而不是返回它。我用一个新的 funcOne 改变了代码片段,向你展示我的想法。
      猜你喜欢
      • 2019-02-26
      • 1970-01-01
      • 1970-01-01
      • 2017-10-26
      • 2017-11-18
      • 2015-06-30
      • 2012-05-26
      • 2018-05-16
      相关资源
      最近更新 更多