【问题标题】:Scala Future with side-affect best practice具有副作用最佳实践的 Scala Future
【发布时间】:2022-02-04 09:38:01
【问题描述】:

如果我希望我的 Scala Future 返回一个值,可以通过等待结果/就绪来保证执行,例如 -

   def longCalculation: Int = {
    Thread.sleep(2000)
    42
  }

  implicit val executionContext = scala.concurrent.ExecutionContext.global

  val aFuture: Future[Int] = Future {  
    longCalculation
//        throw new ArrayIndexOutOfBoundsException // non-fatal exception
//        throw new StackOverflowError() // fatal exception
  }

评估返回具体值的 Future -

  val ready_aFuture_1: Future[Int] = Await.ready(aFutureTest, Duration.Inf)
  val ready_aFuture_2: Option[Try[Int]] = ready_aFuture_1.value
  val ready_aFuture_3: Try[Int] = ready_aFuture_2.get // will never be None, Option is unnecessary.
  val ready_aFuture_4: String = ready_aFuture_3 match {
    case Success(t) => t.toString
    case Failure(e) => e.toString
  }
  println(ready_aFuture_4)

如果我想操纵未来的副作用,我能找到的唯一可以保证执行的方法是 -

val f: Future[Unit] = aFuture.map{ v =>
    println(s"the result of aFuture map is: $v")
  }

   Await.result(f, Duration.Inf)

但这很丑陋,既因为我使用 .map 来表示“副作用”,又因为我们需要保留和使用 Unit 类型。 有没有其他方法可以保证对 Future 的处理会产生“副作用”?

【问题讨论】:

  • 我不知道你为什么认为mapUnit 是“丑陋的”。在我看来,两者都很好。或者按照答案中的建议使用andThen(我发现它不太方便,因为它需要Try,但有时它实际上很有用,这取决于您要如何处理故障)。在我的书中你的 sn-p 中“最丑”的部分是 Await ...在大多数情况下,设计良好的代码不应该显式地等待副作用发生(如果你需要等待它,它是不是真正的副作用)。但是,这当然是“基于意见的”,所以我投票结束这个问题:)
  • 我认为 map 很丑,因为在纯函数式编程中 map 不应该产生副作用,而不是 foreach。此外,我不同意在设计良好的代码中我不应该显式执行 Wait 因为 wait 的目的是为了保证,我的意思是在我的实际场景编程问题中,在 99% 的情况下它是不需要的,但是在生产过程我们要保证我们的执行力。
  • pure 函数式编程中没有副作用 :) 一旦有了副作用,它就不是纯粹的,产生它的函数的名称并不重要.无论如何,如果您不喜欢map,请按照建议使用andThen。我不知道您所说的“必须保证执行”到底是什么意思,但是保证副作用存在的正确方法,如果要查看副作用,而不是阻塞等待函数返回的线程.. . 什么都没有(如果它实际上返回了有用的东西,不暗示阻塞会更合理)。
  • WDYM的执行能保证吗?顺便说一句,也许你想改用foreach
  • 我的意思是,在退出主线程之前,我们要保证side-effect方法已经执行并且执行完毕。 foreach 是不够的,因为主线程可以在 foreach 之前结束。

标签: java multithreading scala jvm


【解决方案1】:

您可能想使用andThen。 scala 文档说:

对这个future的结果应用副作用函数,并用这个future的结果返回一个新的future。

例如,你可以这样写:

val f: Future[Int] = aFuture.andThen { v =>
  println(s"the result of aFuture map is: $v")
}
Await.result(f, Duration.Inf)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-01
    • 2020-04-16
    • 2014-11-18
    • 1970-01-01
    • 1970-01-01
    • 2020-04-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多