【问题标题】:Blocking/non-blocking functions in JavaScript library?JavaScript库中的阻塞/非阻塞函数?
【发布时间】:2026-01-07 03:40:01
【问题描述】:

我正在移植一个库,其中包含需要能够在同步或异步模式下使用的 cpu 昂贵的函数。鉴于它们需要在节点和浏览器中工作,在当前 JavaScript(setTimeout、web-workers 等)中实现这些功能的最佳方法是什么?

【问题讨论】:

  • should I include two versions of each (sync and async) 如果合适的话 - Should I replace the callbacks with promises, or with async/await 就图书馆的消费者而言,技术上是一样的
  • 如果您想要一个同步或异步运行的函数 - 该函数如何知道以哪种方式运行?
  • 嗯,目前是根据是否提供回调
  • 还不错 - 听起来不错
  • 对,但是如果你尝试顺序调用一些这样的函数,你会在回调中的回调中得到一团糟

标签: javascript node.js promise async-await


【解决方案1】:

每个函数我会有两个版本,并且让异步版本返回一个承诺而不是接受一个回调参数。

如何做到这一点取决于您。您可以从字面上返回一个承诺然后解决/拒绝它,或者您可以将函数标记为async,这使它们隐式返回一个承诺,然后返回响应(这就像用一个值解析)。

class LibClass {
  a() { // async a with promises returns Promise<ret>
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        const ret = doWork()
        resolve(ret)
      }, 1)
    })
  }
  a_sync() { // sync a returns ret
    const ret = doWork()
    return ret
  }
  async b(data) { // async function b returns Promise<ret>
    const ret = doWork()
    return ret
  }
}

【讨论】:

    【解决方案2】:

    这听起来你对同步和异步有点困惑。给定函数要么具有同步结果,要么具有异步结果。非此即彼。这个事实取决于函数的作用,而不是调用者的想法或想要的。

    如果一个函数调用任何异步的或可能在其实现中调用任何异步的,那么它的最终结果是异步的,没有办法让它同步。它必须有一个异步接口。您不能提供同步接口,因为结果根本无法同步返回。

    如果一个函数在其实现中没有调用任何异步的东西,那么它就是一个同步函数,你应该给它一个同步接口,因为它总是比异步接口更容易使用,并且同步接口也可以与其他异步代码一起使用所以它非常灵活。

    因此,如果您有一个完全同步的库,您可以同时提供同步和异步接口,但没有理由这样做。只需提供一个同步接口,因为它总是更易于使用。

    而且,库中执行任何异步操作的任何函数都必须具有异步接口。

    因此,选择取决于您在库函数中所做的事情,而不是其他任何事情。


    仅供参考,有时可能会有一个函数有时具有同步结果,有时具有异步结果。典型的例子是当一个值可能已经在本地缓存并立即可用,但如果不在缓存中,则必须从某个远程资源异步检索。在这种情况下,您提供了一个异步接口,即使结果立即可用,您仍然可以异步返回它。这样调用者就可以得到一个统一的接口,无论哪种方式都可以工作,调用者不必编写两种不同的方式来使用你的函数。注意:这应该是库设计中罕见的情况,而不是通常的情况。通常,一个函数要么一直是内部同步的,要么一直是异步的。

    【讨论】:

      【解决方案3】:

      你可以使用 async 关键字 喜欢:

      class LibClass{
            async a(){
               return Promise.resolve('success');
              }
      }
      

      【讨论】:

      • 如果一个函数被标记为async,它已经返回一个Promise。所以在你的例子中你可以return 'success'
      最近更新 更多