【问题标题】:Is Scala ExecutionContext as Class or Method parameter more idiomatic?Scala ExecutionContext 作为类或方法参数更惯用吗?
【发布时间】:2020-03-04 23:12:06
【问题描述】:

每个方法传入ExecutionContext 是否更惯用的Scala

class Foo {
    def bar(a: Int, b: Int)(implicit ec: ExecutionContext): Future[Int] = {
        Future(a + b)
    }

    def baz(a: Int, b: Int)(implicit ec: ExecutionContext): Future[Int] = {
        Future(a - b)
    }
}

或者更好地传递ExecutionContext每个类

class Foo(implicit ec: ExecutionContext) {
    def bar(a: Int, b: Int): Future[Int] = {
        Future(a + b)
    }

    def baz(a: Int, b: Int): Future[Int] = {
        Future(a - b)
    }
}

在 Scala 世界中,一种风格通常更受欢迎,因为它带来的惊喜更少,更容易阅读,还是出于其他原因?如果可能,请提供一些参考。

【问题讨论】:

  • 第二种模式的一个例子是异步数据库驱动程序(如 ReactiveMongo)。这些通常具有您在打开连接时配置的内部 ExecutionContext。然后您在驱动程序上调用查询方法,返回一个 Future,而无需在每次调用时指定 EC。但是,当您想要对结果进行后处理(通过 mapping 来自数据库的 Future)时,您必须为此再次提供自己的 EC。
  • 如果您迁移到效果库(如 ZIO、Monix 或 Cats 效果),整个事情会变得更加清晰。然后你可以组合“任务”,只有在最后才必须提供执行环境(所以没有隐式的 EC 被到处传递)。
  • @Thilo 看来你有一个很好的答案。您能否将其作为答案,包括每种样式的常见用法,尤其是。在现有的图书馆中?
  • 你可以在这里阅读我的建议:viktorklang.com/blog/Futures-in-Scala-protips-1.html

标签: scala future executioncontext


【解决方案1】:

这两个选项有不同的语义,所以都不是惯用的。

第一个选项允许调用者在调用时指定执行上下文,并允许不同的上下文用于不同的调用。

第二个选项要求所有调用使用相同的上下文。

选择取决于您想要的类和方法的语义。

【讨论】:

  • 是否应该在所有调用中使用相同的上下文?老实说,我不明白为什么我会有多个 ExecutionContexts。
  • 不同的调用者可以在不同的上下文中使用相同的无状态/不可变类
  • 您几乎肯定希望有一个单独的 ExecutionContext 来处理任何阻塞,最重要的是,为不同的子系统(数据库、外部 HTTP 调用、内部服务调用)设置不同的 ExecutionContext 可能是有意义的以便您可以单独配置它们(例如不同数量的线程)
  • 那么一般来说第一个比较推荐?
  • 这真的取决于具体情况。对于Future(a+b),您也可以使用默认的全局执行上下文(通常推荐)。总是把它留给调用者隐含是最常见的做法(只是有点丑陋的样板)。
猜你喜欢
  • 2018-06-28
  • 2015-02-07
  • 2015-06-30
  • 1970-01-01
  • 2013-10-19
  • 2019-01-19
  • 2023-04-01
  • 2019-10-07
  • 1970-01-01
相关资源
最近更新 更多