【问题标题】:Abstraction for asynchronous computation that cannot fail不能失败的异步计算的抽象
【发布时间】:2016-01-09 05:57:37
【问题描述】:

Scala Futures 是异步计算的一个很好的抽象,可能会失败。当我知道不可能失败时,我应该使用什么抽象?

这是一个具体的用例:

case class Service123Error(e: Throwable)

val f1: Future[User] =
  service123.call()

val f2: Future[Either[Service123Error, User]] =
  f1.map(Right.apply)
    .recover { case e => Left(Service123Error(e)) }

在这段代码中,类型没有模拟f2 总是成功完成的事实。给定几个类似于f2 的值,我知道我可以Future.sequence 覆盖它们(即没有快速失败的行为),但是这些类型没有携带此信息。

【问题讨论】:

  • 无关:引用Either ScalaDoc约定规定Left 用于失败,Right 用于成功
  • 我总是把它搞砸了......已修复
  • 如果service123.call()不能失败,Service123Error类型代表什么?此外,Future API 代表 scala.util.{Success, Failure} 类型的失败和成功……如果您将 Failure 映射到 Either,那么它就不再是关于 Future API 了,不是吗?
  • service123.call() 可能会失败,但 f2 不能,因为它会捕获所有带有 recover 的错误。我对Future[Either] 的看法是它有3 个选项,Future.failed(e)Future.successful(Left(l))Future.successful(Right(r)),有3 个不同的含义,我想搭上第一个选项。
  • 由于f2 是异步计算,因此可能会出现故障。如果您只认为system123 中的特定错误是可恢复的(通常全部捕获不是一个好兆头),我可能会将system123.call 的签名更改为Either[..., User]

标签: scala asynchronous future scalaz


【解决方案1】:

如果Either 带有错误信息,我不会将其粘贴到Future 中。只需使用未来失败的一面。

Future(Right(User))           -> Future[User](User)
Future(Left(Service123Error)) -> Future[User](throw Service123Error)

【讨论】:

  • 我的问题的重点是,如果它是Future[T, Service123Error],为什么不呢,但是对于Future[T, Throwable],我无法在类型中编码我正在处理Service123Error 和没有任何例外... Future.sequence 在您的示例中也不起作用(它在第一个异常中快速失败)。
  • 您可以对失败值进行模式匹配,并根据需要区分多种不同类型的错误!
  • Throwable 不是我控制的密封特征,所以这就像放弃类型安全。我不想让case _ => ??? 在我的代码中到处闲逛。
  • 嗯,这就是您使用 Future API 所拥有的。我仍然建议您将其与模式匹配一​​起使用,而不是不必要地弄乱您的类型以提高类型安全性。
猜你喜欢
  • 2012-05-14
  • 2017-07-29
  • 2019-05-27
  • 1970-01-01
  • 2018-01-20
  • 1970-01-01
  • 2015-12-26
  • 2022-01-22
  • 2020-10-08
相关资源
最近更新 更多