我如何等待 Scala future 的 onSuccess 回调完成?
How do I wait for a Scala future's onSuccess callback to complete?
在 Scala 中,我可以使用 Await
等待未来完成。但是,如果我已经在那个 future 完成后注册了一个回调到 运行,我怎么能不仅等待 future 完成而且还等待那个回调完成?
这里有一个最小但完整的程序来说明问题:
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.Duration
import scala.concurrent.{ Await, Future }
object Main {
def main(args: Array[String]): Unit = {
val f: Future[Int] = Future(0)
f.onSuccess { case _ =>
Thread.sleep(10000)
println("The program waited patiently for this callback to finish.")
}
// This waits for `f` to complete but doesn't wait for the callback
// to finish running.
Await.ready(f, Duration.Inf)
}
}
我希望输出为:
The program waited patiently for this callback to finish.
反而没有输出;程序在回调完成前退出。
请注意,这与等待未来完成的问题不同,后者已在 this question 上得到解答。
不要使用 onSuccess 回调,而是在 Future.map 调用中产生副作用。这样,你就有了一个 Future[Unit] 来使用 Await。
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.Duration
import scala.concurrent.{ Await, Future }
object Main {
def main(args: Array[String]): Unit = {
val f: Future[Int] = Future(0)
val f2: Future[Unit] = f.map { x =>
Thread.sleep(10000)
println("The program waited patiently for this callback to finish.")
}
Await.ready(f2, Duration.Inf)
}
}
请注意,如果您只想在成功的情况下执行副作用(如您的示例),map 是合适的。如果你想在失败的情况下也执行副作用,andThen 是正确的方法。请参阅 Roland Kuhn 在 scala-user 上的 post。
此外,请不要在生产代码附近的任何地方使用Thread.sleep。
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.Duration
import scala.concurrent.{ Await, Future }
import scala.util._
object Main {
def main(args: Array[String]): Unit = {
val f1: Future[Int] = Future(0)
val f2 = f1 andThen {
case Success(v) =>
Thread.sleep(10000)
println("The program waited patiently for this callback to finish.")
case Failure(e) =>
println(e)
}
Await.ready(f1, Duration.Inf)
println("F1 is COMPLETED")
Await.ready(f2, Duration.Inf)
println("F2 is COMPLETED")
}
}
打印:
F1 is COMPLETED
The program waited patiently for this callback to finish.
F2 is COMPLETED
使用promise就更清楚了:
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.Duration
import scala.concurrent._
import scala.util._
object Main {
def main(args: Array[String]): Unit = {
val f: Future[Int] = Future(0)
val p = Promise[Unit]()
p.future.onSuccess { case _ =>
println("The program waited patiently for this callback to finish.")
}
f.onSuccess { case _ =>
Thread.sleep(10000)
p.success(())
}
Await.ready(f, Duration.Inf)
println("F is COMPLETED")
Await.ready(p.future, Duration.Inf)
println("P is COMPLETED")
}
}
打印:
F is COMPLETED
P is COMPLETED
The program waited patiently for this callback to finish.
在 Scala 中,我可以使用 Await
等待未来完成。但是,如果我已经在那个 future 完成后注册了一个回调到 运行,我怎么能不仅等待 future 完成而且还等待那个回调完成?
这里有一个最小但完整的程序来说明问题:
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.Duration
import scala.concurrent.{ Await, Future }
object Main {
def main(args: Array[String]): Unit = {
val f: Future[Int] = Future(0)
f.onSuccess { case _ =>
Thread.sleep(10000)
println("The program waited patiently for this callback to finish.")
}
// This waits for `f` to complete but doesn't wait for the callback
// to finish running.
Await.ready(f, Duration.Inf)
}
}
我希望输出为:
The program waited patiently for this callback to finish.
反而没有输出;程序在回调完成前退出。
请注意,这与等待未来完成的问题不同,后者已在 this question 上得到解答。
不要使用 onSuccess 回调,而是在 Future.map 调用中产生副作用。这样,你就有了一个 Future[Unit] 来使用 Await。
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.Duration
import scala.concurrent.{ Await, Future }
object Main {
def main(args: Array[String]): Unit = {
val f: Future[Int] = Future(0)
val f2: Future[Unit] = f.map { x =>
Thread.sleep(10000)
println("The program waited patiently for this callback to finish.")
}
Await.ready(f2, Duration.Inf)
}
}
请注意,如果您只想在成功的情况下执行副作用(如您的示例),map 是合适的。如果你想在失败的情况下也执行副作用,andThen 是正确的方法。请参阅 Roland Kuhn 在 scala-user 上的 post。
此外,请不要在生产代码附近的任何地方使用Thread.sleep。
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.Duration
import scala.concurrent.{ Await, Future }
import scala.util._
object Main {
def main(args: Array[String]): Unit = {
val f1: Future[Int] = Future(0)
val f2 = f1 andThen {
case Success(v) =>
Thread.sleep(10000)
println("The program waited patiently for this callback to finish.")
case Failure(e) =>
println(e)
}
Await.ready(f1, Duration.Inf)
println("F1 is COMPLETED")
Await.ready(f2, Duration.Inf)
println("F2 is COMPLETED")
}
}
打印:
F1 is COMPLETED
The program waited patiently for this callback to finish.
F2 is COMPLETED
使用promise就更清楚了:
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.Duration
import scala.concurrent._
import scala.util._
object Main {
def main(args: Array[String]): Unit = {
val f: Future[Int] = Future(0)
val p = Promise[Unit]()
p.future.onSuccess { case _ =>
println("The program waited patiently for this callback to finish.")
}
f.onSuccess { case _ =>
Thread.sleep(10000)
p.success(())
}
Await.ready(f, Duration.Inf)
println("F is COMPLETED")
Await.ready(p.future, Duration.Inf)
println("P is COMPLETED")
}
}
打印:
F is COMPLETED
P is COMPLETED
The program waited patiently for this callback to finish.