La andThen
signification que j’ai tirée de cette answer est un composeur de fonctions.
Dis ça
f andThen g andThen h
sera égal à
h(g(f(x)))
Cela implique que le h function
recevra les entrées de g(f(x))
Sauf pour la andThen
dans Future
, toute la fermeture de ce qui suit et puis reçoit toujours le résultat de la Future
originale.
Future{
1
}.andThen{ case Success(x) =>
println(x) // print 1
Thread.sleep(2000)
x * 2
}.andThen{ case Success(x) =>
println(x) // print 1
Thread.sleep(2000)
x * 2
}
comparer aux
val func: Function1[Int, Int] = { x: Int =>
x
}.andThen { y =>
println(y) // print 1
y * 2
}.andThen { z =>
println(z) // print 2
z * 2
}
func(1)
Quelle est la raison pour que Future :: andThen (s) reçoive le même résultat de Future original au lieu de chaîner Future? J'ai observé que ces chaînes et puis seront exécutés de manière séquentielle, donc la raison peut ne pas être à des fins parallèles.
scala.concurrent.Future
est conçu comme un compromis entre deux approches asynchrones:
Lecture de la documentation de Future.andThen
:
Applique la fonction d'effet secondaire au résultat de cet avenir, et renvoie un nouvel avenir avec le résultat de cet avenir.
Donc, andThen
provient probablement de l’univers OOP. Pour obtenir un résultat similaire à Function1.andThen
, vous pouvez utiliser map
method:
Future(1).map {_ * 2}.map {_ * 2}
andThen
diffère de onComplete
avec une petite chose: l’avenir résultant de andThen
retournant toujours le même résultat, mais attendra que l’observateur fourni revienne ou jette quelque chose. C'est pourquoi il est écrit dans la documentation:
Cette méthode permet de faire en sorte que les rappels soient exécutés dans un fichier ordre spécifié.
Notez également la troisième ligne de docs:
Notez que si l'un des rappels chaînés et Puis lève une exception, cette exception n'est pas propagée aux rappels ultérieurs, puis .. ... Au lieu de cela, les callbacks suivants etThen reçoivent la valeur d'origine de cet avenir.
Donc, il ne fait absolument rien avec le nouveau résultat Future
. Ne pouvait même pas le gâter avec son exception. Ceci andThen
et onComplete
juste une liaison séquentielle et parallèle des observateurs.
Permettez-moi de résumer cette belle discussion.
Disons que nous avons tf: Future[T] =...
et deux fonctions, f: T => U
et g: U => V
Nous pouvons faire vf: Future[V] = tf map f map g
, identique à vf: Future[V] = tf map (f andThen g)
Dans un autre cas d'utilisation, avec fp: PartialFunction[T, U]
et gp: PartialFunction[U, V]
, , Nous pouvons exécuter tf1: Future[T] = tf andThen fp andThen gp
- ces fonctions partielles seront appelées sur la valeur produite par tf, sans effet extérieur - seuls les effets secondaires se produisent. Cette séquence attend fp
avant d'appeler gp
.
Encore une autre opération future, onComplete, fonctionne comme ceci: ayant f: Try[T] => U
, l'appel tf onComplete f
appellera f
même si l'avenir se terminait par une erreur; le résultat de tf onComplete f
est de type Unit
.
De plus, si votre fonction f
produit une Future
, vous devrez utiliser flatMap
.