【问题标题】:How to call async function from web of non-async functions如何从非异步函数网络调用异步函数
【发布时间】:2019-12-01 00:43:00
【问题描述】:

我在一个中等规模的 node.js 应用程序中工作,其中包含一系列调用其他同步函数等的同步函数。为了简单起见,我们只说这些函数在此之前都没有返回 Promises。

function a(){
  ...
  return c();
}
function b(){
  ...
  return c();
}
function c(){
  ...
  return e();
}
function d(){
  ...
  return e();
}
function e(){
   // Do stuff
}

它实际上比这复杂得多,并且有一套完整的单元/集成测试也可以调用这些函数。

我们现在需要函数 e() 来等待异步函数的结果:

function e(){
   const someData = await someAsyncFunction();
   const dataINeedNow = someData.dataINeedNow;
   // Do something with dataINeedNow
}

async function someAsyncFunction(){
  ...
  return await someExternalService();
}

似乎普遍的看法是,一旦你开始返回 Promise,就应该继续返回 Promise。在上面的示例中,这将涉及将 a、b、c、d 和 e 全部设为async,但实际上它会在我们的应用程序中涉及大约 100 次更改。

有没有一种方法可以在 node.js 应用程序的内部调用 await someExternalService(); 而无需进行重大重构?

【问题讨论】:

  • 改变一个一切都依赖于的函数的性质的一个重大改变。你无法真正避免重大的重构。但是,也许您可​​以avoid making the function e itself asynchronous,例如通过更改传递给它的参数?
  • 一切都必须是异步的,直到真正需要等待结果的函数才能继续该过程。如果您不希望使用回调函数或实际的 Promise then 功能而不是 await
  • 如果您从头开始,您会创建 a、b、c、d 和 e async,但请记住,在 Promise 之后但在引入 AsyncFunctions 之前,Javascript 存活了相当长的一段时间。即使 a、b、c、d (如问题中总结的那样)保持非异步函数,它们仍将返回承诺。使它们async将(a)使await可用,(b)保证在更大范围的情况下返回一个promise,(c)保证错误异步抛出。如果没有这些功能,您仍然可以从您的函数中获得基本的异步功能
  • 你的函数 e 和 await 将无法工作,因为函数 e 不是异步的 - 异步就像病毒,一旦引入,它就会迅速传播
  • 所以一旦我与第三方函数 async 集成,我应该在我的应用程序层次结构中创建使用它的每个函数 async (可能有 100 多个更改)?如果这是正确的答案,我可以做到,但我很惊讶在 Javascript 中实际上没有其他方法可以解决这个问题。

标签: javascript node.js asynchronous promise async-await


【解决方案1】:

您可能应该重写整个链以返回承诺以保持一致性并且不会使您的代码非常混乱。

但是,根据您编写问题的方式,如果您真的要返回每个后续调用的结果,您可以在嵌套之外处理承诺结果。

function e 上返回一个承诺,该承诺将一直返回到您的原始呼叫

    function e(){
        console.log("did e");
        const prom = new Promise((resolve)=>{
            setTimeout(()=>{
              console.log("resolved async");
              resolve("dataResolve")
            },1000)      
        });
        return prom;
    }

使用来自a的响应写Do something with dataINeedNow

a().then((resArg)=>{
    f(resArg);
})

查看示例here

【讨论】:

  • 同意。我试图鼓励其他开发人员完全避免 async/await。它试图让 JavaScript 像其他东西一样读取/执行。更好地理解回调/承诺并正确使用它们。
【解决方案2】:

只需使用then/catch 处理e() 中的Promise。

你的e() 看起来像:

function e(){
   someAsyncFunction()
   .then(data => {
      const dataINeedNow = data.dataINeedNow;
      // Do something with dataINeedNow;
    })
   .catch(e => {
        // Do something if someExternalService throws rejection
        console.log(e);
    })
}

function someAsyncFunction(){
  ...
  // This works provided someExternalService() returns a Promise.
  return someExternalService();
}

async/await 只是 Promise 处理的语法糖。我不喜欢它,因为它为不想学习如何在 JavaScript 中正确处理并发的开发人员提供了一种使他们的应用程序伪同步的方法。

如果您觉得这很陌生,我建议您查看 JavaScript 中的并发模式。特别是回调和 Promise 链。

【讨论】:

    猜你喜欢
    • 2020-03-09
    • 2019-08-18
    • 1970-01-01
    • 2020-04-20
    • 1970-01-01
    • 2012-07-25
    • 1970-01-01
    • 2022-11-16
    • 2017-08-13
    相关资源
    最近更新 更多