【问题标题】:Function conditionally runs async code, but needs to be run sync at other times. How to keep it DRY?函数有条件地运行异步代码,但需要在其他时间运行同步。如何保持干燥?
【发布时间】:2020-11-09 02:03:23
【问题描述】:

假设我有这个函数doSomeThing(),它有条件地在工作线程(异步)中运行一些非常昂贵的代码,但大多数时候它需要运行同步。

有什么方法可以同步使用这个异步函数吗?我认为没有。

那么除了创建两个几乎相同的函数之外,我还有什么其他选择,它们的区别仅在于同步与异步方法?是否有一些我忽略的 DRYer 替代方案?

async function doSomeThing(input, shouldDoExpensiveStuff) {
  let output = parseInt(input)

  // ... A lot of shared logic

  if (shouldDoExpensiveStuff) {
    output = await offloadToWorker(input);
  } else {
    output += 1;
  }

  // ... A lot of other shared logic

  return output;
}

我知道我可以将很多共享逻辑转移到新的 doSomeThingSyncdoSomeThingAsync 可以共享的单个函数中,但它确实看起来非常不理想且乏味,我可能需要使用数字来执行此操作功能。

我控制 JS 执行环境,所以浏览器兼容性不是问题。通过 Babel 进行的任何花哨的 ECMA 魔法都是公平的游戏。

【问题讨论】:

  • 同步运行是否有特定原因?我的意思是:当你执行异步函数时,它不需要做昂贵的事情,它几乎和同步函数一样快,调用这个函数的函数并不关心,因为它期望返回一个承诺无论如何,它只会按照这个承诺行事。我认为这是非常干净的代码。
  • 好问题。原因是第三方库是调用者,而调用者不是async function。因此,调用返回 promise 的函数的结果会导致存储的值成为待处理的 promise,而不是预期的结果。
  • 听起来你已经想通了。将所有共享逻辑移至共享函数。
  • 但是第三方不应该知道它调用的函数的签名吗?当您实施您的建议(2 个函数,一个异步一个不)时,第三方也应该知道要调用哪一个。如果第三方函数需要同步结果,则您不能在函数中运行异步工作器并使用该结果。
  • @Slbox 听起来你确实有两个独立的函数,它们做不同的事情并在不同的地方调用(一个做昂贵的事情,另一个不做)。您能否发布您正在处理的具体代码?共享代码究竟做了什么,它如何与inputoutput 交互?为什么你有这么多遵循这种模式的功能,它们都做同样的事情吗?

标签: javascript ecmascript-6 async-await es6-promise ecmascript-next


【解决方案1】:

这是一个如何让同一个函数立即或异步返回的示例:

const fn = sync => sync
  ? 'foo returned immediately'
  : new Promise(resolve => setTimeout(() => resolve('bar returned after 1 second'), 1000));

const main = async () => {
  const foo = fn(true);
  console.log(foo); // foo returned immediately
  const bar = await fn(false);
  console.log(bar); // bar returned after 1 second
}

main();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-23
    • 1970-01-01
    相关资源
    最近更新 更多