【问题标题】:Why do I need to use andThen in order to pattern match Futures?为什么我需要使用 andThen 来匹配 Futures?
【发布时间】:2017-05-18 11:33:16
【问题描述】:

我发现为了模式匹配Future毛皮Success/Failure,我需要使用andThen(或onCompleteonSuccess...)并且不能使用map .这是为什么呢?

我想做的事情(简单来说,我也在匹配Success等等):

val f1 = Future(throw new Exception("Oops"))
f1 map { case Failure(e) => ??? }

给予:

error: constructor cannot be instantiated to expected type;
 found   : scala.util.Failure[T]
 required: Nothing
       f1 map { case Failure(e) => ??? }

我最终做了什么:

val f1 = Future(throw new Exception("Oops"))
f1 andThen { case Failure(e) => ??? }

我想了解为什么这里不能使用map

【问题讨论】:

    标签: scala pattern-matching future


    【解决方案1】:

    答案在map 的签名中:它接受A => B 并返回Future[B]。如果你愿意,你可以看看Future,如下:

    type Future[A] = Async[Either[Throwable, A]]
    

    Future#mapFuture#flatMapFuture.apply 将这个类型的“堆栈”视为一个带有孔的大东西(Future 基本上是一个特殊的单子变换器)。当您在Futuremap/flatMap 时,您只是在内部A 上操作。

    【讨论】:

    • 所以你的意思是我只对Exception 本身进行操作,其余的(FutureFuture#Failure)是“扁平化”的,对吗?
    • 反之亦然:使用map,您只能对A 进行操作。为了能够对Exception 执行操作,您需要其他运算符,例如recovertransform
    • 非常感谢您的澄清!
    • 这对于稍微接触“Monad Transformer”概念非常有帮助。
    【解决方案2】:

    因为类型签名不正确。当您想映射 Future[A] 时,您需要提供一个函数,该函数采用 A 并生成 B,这似乎不是您正在做的事情。你要找的是recover:

    f1 recover { case e => // e is already a `Throwable` here ??? }
    

    【讨论】:

    • 我也知道recover。使用andThen 来处理SuccessFailure 而不是map 然后recover 是否有意义(即不是一个坏习惯)?
    • @BobDem 我会说maprecover 更惯用。请注意andThen 上的注释:“请注意,如果链接的andThen 回调之一抛出异常,则该异常不会传播到后续的andThen 回调。相反,后续的andThen 回调将被赋予这个未来的原始价值。”
    • 这是一个非常明显的缺点,尽管它看起来更干净(对我来说)而且我很乐意将它用于所有事情。是这样吗?通常的做法是用map 包裹Futures 来操作成功,recover 来操作失败?
    • @BobDem 是的,这是我在使用Future 的大多数地方使用的一般做法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-18
    • 2020-07-27
    • 1970-01-01
    • 1970-01-01
    • 2011-03-22
    相关资源
    最近更新 更多