【问题标题】:Why the *Async naming convention for functions returning Deferreds?为什么返回 Deferreds 的函数使用 *Async 命名约定?
【发布时间】:2019-08-02 03:31:12
【问题描述】:

Intellij 有一个检查(即 lint 检查),它告诉您返回 Deferred 的函数应该命名为以 Async 结尾的东西。

像这样的命名约定在动态类型语言中对我来说很有意义。但是 Kotlin 有这么好的类型检查器和工具生态系统,那么为什么要依赖约定呢?

特别是因为 Kotlin 协程烘焙 structured concurrency ,该函数可能还会采用 CoroutineScope 参数,这将在调用站点提供相同的视觉提示:

suspend fun doStuff() = coroutineScope {
  doStuffAsync(this /* CoroutineScope */).await()
  //...
}

作为旁注,我了解检查的信息,即您很少需要返回 Deferred 而不是 suspend 函数的函数。那不是我的问题。我的问题假设您知道自己在做什么并且想要Deferred

【问题讨论】:

    标签: kotlin kotlin-coroutines


    【解决方案1】:

    首先,函数几乎不应该返回来自async 块的Deferred。由调用者将一些工作单元包装到 async 中,同时在前台执行其他工作,然后在返回之前对异步结果使用 await,并将所有代码包装在 coroutineScope 中。

    Deferred 实例的预期来源是 Kotlin 协程和第 3 方异步 API 之间的适配层。对于此类调用,将Async 放在名称中确实有意义,甚至某些Java API 也遵循此约定。例如,您可能有一个

    fun fetchOrder(id: String): Deferred<Order>
    

    并将其用作

    val orderCancelled = fetchOrder(orderId).isCancelled
    

    此代码是类型安全且类型正确的,不会导致任何编译器错误。看起来它正在从远程系统获取订单,然后检查订单状态(是否已取消),但实际上它正在获取Deferred&lt;Order&gt; 并检查Deferred 是否已取消。因为你的函数名缺少Async,所以这种错误很难发现。

    是的,您也可以请求 IDE 为您提供返回类型,但您可能需要一段时间才能怀疑发生了什么。

    【讨论】:

      【解决方案2】:

      Deferred 不返回实际值,而是“一个轻量级的非阻塞未来,表示承诺稍后提供结果”。

      正如您从方法名称中看不到的那样,“我们使用“...Async”后缀命名此类函数,以强调它们仅启动异步计算并且需要使用生成的延迟值来获得结果这一事实” .

      因此,您的代码的读者可以立即看到您的方法没有返回实际值,但还必须对其调用 await()


      关于suspend 函数的第二点:

      通常情况相反,xyzAsync() 函数调用suspend xyz() 函数。

      因为返回 Deferred 的函数可以从任何地方调用,而不仅仅是从挂起函数。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-17
        • 2020-01-06
        相关资源
        最近更新 更多