Как дождаться завершения обратного вызова onSuccess в Scala future?
в Scala, я могу использовать 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)
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.
вместо этого нет вывода; программа завершает работу до обратного вызова заканчивает.
обратите внимание, что это не та же проблема, что и ожидание завершения будущего, на которое ранее был дан ответ в этот вопрос.
2 ответов
Не используйте обратный вызов onSuccess, а вместо этого сделайте побочный эффект в будущем.вызов карты. Таким образом, у вас есть будущее[устройство] для использования Await on.
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-правильный метод для использования. Смотрите это в должности от Роланда Куна на scala-user.
также, пожалуйста, не нить использовать.спать рядом производственный код.
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
использование обещаний еще более ясно:
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.