【问题标题】:Any drawbacks of having all functions async? [closed]使所有功能异步有什么缺点吗? [关闭]
【发布时间】:2019-06-08 13:09:41
【问题描述】:

较新的 node js 有 async await,这真的很酷,因为它让代码看起来更好。

我想知道让每个类方法异步是否是个好主意,即使它不需要返回承诺?

在我的用例中,我实际上有点需要它,因为我试图在多个子进程之间共享依赖关系,并且我正在使用代理和子进程通信的组合来实现这一点。显然我需要 promise,因为我需要等待进程响应或发送消息。

但这是否有任何潜在的副作用,也许是长期的?

为了更清楚,我想这样做只是为了使用酷语法。

const database = CreateProxy('database');
await database.something();

来自另一个进程。

与一些只从父进程请求something 的代码相比

process.send('getSomethingFromDb');

在引擎盖下两者都使用消息传递,但第一个让它看起来好像不在表面上

【问题讨论】:

  • 这不是没有一点额外的开销。
  • 诚然,我是基于在 C# 中而不是 JS 中处理项目的,但很高兴知道哪些方法依赖于外部标注等,因为它们被标记为 async。不禁觉得标记所有内容 async 有点混乱。
  • 是的,投票结果如何?

标签: javascript node.js asynchronous promise child-process


【解决方案1】:

调用async 函数的结果将始终为Promise,无论该函数是否实现任何异步行为。

const asyncTest = async () => 3;
console.log(asyncTest()); // logs 'Promise {<resolved>: 3}'

因此,您必须始终确保使用await 调用此类函数。但这纯粹是一个舒适的问题,即使对你来说也是如此。而且,创建和解析 Promises 会为每个函数调用增加一点时间,所以如果性能很关键,你应该避免大量调用 async 函数,如果可以避免的话。

【讨论】:

    【解决方案2】:

    这个概念是Occam's razor 的主题。没有好处,也可能有坏处。

    额外的开销(CPU 和时间)是问题之一。承诺需要一些时间和资源来解决。这可能需要不到一毫秒的时间,但可能会累积延迟。

    另一个问题是异步性具有传染性,一旦它达到模块范围,async IIFE 应该在任何地方使用 - 因为 top-level await 尚不支持:

    module.export = (async () => {
      await require('foo');
    
      // await was accidentally dropped
      // this results in race condition and incorrect error handling
      require('foo');
      ...
    })();
    

    这是一个使错误处理复杂化的缺点的一个很好的例子:

    async function foo() {
      throw new Error('foo');
    }
    
    async function bar() {
      try {
        return foo();
      } catch (err) {
        console.log('caught with bar');
      }
    }
    
    
    bar(); // UnhandledPromiseRejectionWarning: Error: foo
    

    尽管async 中的控制流看起来是同步的,但错误的处理方式不同。 foo 返回被拒绝的承诺,并且在 async 函数中不使用 try..catch 处理返回的值。 bar 不会处理拒绝。

    这不会发生在常规函数中:

    function foo() {
      throw new Error('foo');
    }
    
    function bar() {
      try {
        return foo();
      } catch (err) {
        console.log('caught with bar');
      }
    }
    
    
    bar(); // caught with bar
    

    设计为同步工作的第三方库可能会使事情变得更加复杂。

    【讨论】:

    • 使用.catch 子句实际上更容易处理错误:foo().catch((err) =&gt; {}); try/catch 无论如何都是一团糟。 async 函数的一个更好的事情是你不需要考虑使用 try/catch 或使用 .catch... 只需在同步和异步函数上使用 catch
    • 我第一次阅读时并不明显,但它是 UnhandledPromiseRejectionWarning 而不是 'caught with bar' 的原因是 return foo(); 中缺少等待。如果您等待它被 try / catch 捕获。如果你返回 Promise,这是一个未捕获的错误
    • @carlosvini 这是正确的,捕捉它的方法是try { return await foo() }...。这说明async 函数由于语义上的差异,不能仅仅用作常规函数的直接替换。
    【解决方案3】:

    我想知道让每个类方法异步是否是个好主意, 即使它不需要返回一个承诺?

    你的代码可以工作,但我不推荐它有两个原因:

    • 不必要的内存/cpu 使用率

    • 这会使您的代码难以理解。了解哪个函数是异步的或同步的对于了解系统如何工作以及它在做什么很重要。

    【讨论】:

    • 很好地指出了可读性的重要性——在我看来,它占了编码的 90%!
    猜你喜欢
    • 2017-04-03
    • 1970-01-01
    • 2023-03-03
    • 1970-01-01
    • 2021-12-18
    • 1970-01-01
    • 2021-12-26
    • 2016-02-23
    • 2017-04-01
    相关资源
    最近更新 更多