【问题标题】:Execute operation on Future's value for its side effects, discarding result and retaining original value, but retaining order of operation对 Future 的值执行操作,因为它的副作用,丢弃结果并保留原始值,但保留操作顺序
【发布时间】:2019-11-06 17:20:02
【问题描述】:

假设我有以下操作必须按顺序进行

  1. 获取博文
  2. 后分析
  3. 转发博文

在代码中可能如下所示:

val blogPostFut: Future[BlogPost] = blogService.getPost(postId)
val afterAnalytics: Future[BlogPost] = blogPostFut.flatMap(blogPost =>
  val ignoredResponse: Future[Analytics] = analyticsService.sendAnalytics(blogPost)
  ignoredResponse.map(_ => blogPost)  // <-- THIS BOTHERS ME
)
val finalValue: Future[ForwardResult] = afterAnalytics.flatMap(blogPost =>
  forwardService.forward(blogPost)
)

我很困扰,为了确保正确的执行顺序,我必须在 ignoredResponse 中传递 blogPost 以确保它可用于第 3 步。

如果我能做这样的事情,我会很高兴:

blogPostFut.magicalFlatMap(analyticsService.sendAnalytics)

magicalFlatMap 可以这样实现:

// pseudocode
def magicalFlatMap[A,B](f: A => Future[B]): Future[A] = f().map(_ => this.value)

magicalFlatMap 是否存在于 Scala 标准库或 Cats 中?是否可以mapFuture 产生副作用,同时自动保留原始Future 的值和严格的操作顺序?

【问题讨论】:

    标签: scala future scala-cats


    【解决方案1】:

    试试Future.andThen 的副作用

    for {
      blogPost <- blogService.getPost(postId).andThen { case Success(post) => analyticsService.sendAnalytics(post) }
      finalValue <- forwardService.forward(blogPost)
    } yield {
      finalValue
    }
    

    这是一个虚拟示例

      val result = for {
        v1 <- Future(1)
        v2 <- Future(v1 + 2).andThen { case  Success(v) => println(v) }
        v3 <- Future(v1 + v2)
      } yield {
        v3
      }
    
      result.foreach(println)
    

    应该输出哪个

    3
    4
    

    我们也可以

    for {
      blogPost   <- blogService.getPost(postId) 
      _          <- analyticsService.sendAnalytics(blogPost)
      finalValue <- forwardService.forward(blogPost)
    } yield {
      finalValue
    }
    

    但是在这种情况下,analyticsService.sendAnalytics(blogPost) 中的失败会导致整个理解短路,这可能是不可取的。

    【讨论】:

    • 这不会取消步骤 3 发生 步骤 2 之后的保证吗?
    • 我的理解是,由于理解的性质,第 3 步仍然保证在第 2 步之后发生。
    • 该方法上的 java 文档似乎确实证实了这一点。谢谢!
    【解决方案2】:

    【讨论】:

      猜你喜欢
      • 2015-05-30
      • 1970-01-01
      • 2018-02-09
      • 2017-04-04
      • 2020-05-27
      • 1970-01-01
      • 1970-01-01
      • 2012-01-28
      • 2021-02-23
      相关资源
      最近更新 更多