Angenommen , ich habe mehrere Futures und müssen warten , bis entweder einer von ihnen ausfällt oder alle von ihnen erfolgreich zu sein.
Zum Beispiel: Let gibt es 3 - Futures: f1
, f2
, f3
.
Wenn dies
f1
erfolgreich ist undf2
fehlschlägt, warte ich nicht darauff3
(und gebe den Fehler an den Client zurück).Wenn dies
f2
fehlschlägtf1
undf3
noch ausgeführt wird, warte ich nicht auf sie (und gebe einen Fehler zurück ).Wenn es
f1
gelingt und dannf2
gelingt, warte ich weiterf3
.
Wie würden Sie es implementieren?
scala
concurrency
future
Michael
quelle
quelle
Antworten:
Sie können stattdessen ein Verständnis wie folgt verwenden:
In diesem Beispiel werden die Futures 1, 2 und 3 parallel gestartet. Dann warten wir zum Verständnis, bis die Ergebnisse 1 und dann 2 und dann 3 verfügbar sind. Wenn entweder 1 oder 2 fehlschlägt, werden wir nicht mehr auf 3 warten. Wenn alle 3 erfolgreich sind, enthält der
aggFut
Wert ein Tupel mit 3 Slots, das den Ergebnissen der 3 Futures entspricht.Wenn Sie nun das Verhalten benötigen, bei dem Sie aufhören möchten zu warten, wenn sagen, dass fut2 zuerst fehlschlägt, werden die Dinge etwas schwieriger. Im obigen Beispiel müssten Sie warten, bis fut1 abgeschlossen ist, bevor Sie feststellen, dass fut2 fehlgeschlagen ist. Um das zu lösen, können Sie Folgendes versuchen:
Dies funktioniert nun korrekt, aber das Problem besteht darin, zu wissen, welche
Future
zu entfernen sind,Map
wenn eine erfolgreich abgeschlossen wurde. Solange Sie eine Möglichkeit haben, ein Ergebnis richtig mit der Zukunft zu korrelieren, die dieses Ergebnis hervorgebracht hat, funktioniert so etwas. Es entfernt nur rekursiv abgeschlossene Futures von der Karte und ruft dannFuture.firstCompletedOf
die verbleibenden auf,Futures
bis keine mehr übrig sind, und sammelt die Ergebnisse auf dem Weg. Es ist nicht schön, aber wenn Sie wirklich das Verhalten brauchen, über das Sie sprechen, dann könnte dies oder etwas Ähnliches funktionieren.quelle
fut2
es vorher fehlschlägtfut1
? Warten wirfut1
in diesem Fall noch? Wenn wir wollen, ist es nicht genau das, was ich will.onFailure
Installationsprozedur fürfut2
schnell zum Scheitern verurteilt, und einonSuccess
aufaggFut
bis Griff Erfolg. Ein Erfolg beiaggFut
Implikationenfut2
wurde erfolgreich abgeschlossen, sodass nur einer der Handler aufgerufen wird.Sie können ein Versprechen verwenden und ihm entweder den ersten Fehler oder den endgültig abgeschlossenen aggregierten Erfolg senden:
Dann können Sie
Await
auf das Ergebnis,Future
wenn Sie blockieren möchten, oder nurmap
in etwas anderes.Der Unterschied zum Verständnis besteht darin, dass hier der Fehler des ersten fehlschlägt, während beim Verständnis der erste Fehler in der Durchlaufreihenfolge der Eingabesammlung angezeigt wird (selbst wenn ein anderer zuerst fehlgeschlagen ist). Beispielsweise:
Und:
quelle
Hier ist eine Lösung ohne Schauspieler.
quelle
Sie können dies nur mit Futures tun. Hier ist eine Implementierung. Beachten Sie, dass die Ausführung nicht vorzeitig beendet wird! In diesem Fall müssen Sie etwas Anspruchsvolleres tun (und die Unterbrechung wahrscheinlich selbst implementieren). Wenn Sie jedoch nicht weiter auf etwas warten möchten, das nicht funktioniert, müssen Sie darauf warten, dass das erste fertig ist, und aufhören, wenn entweder nichts mehr übrig ist oder Sie eine Ausnahme haben:
Hier ist ein Beispiel dafür in Aktion, wenn alles in Ordnung ist:
Aber wenn etwas schief geht:
quelle
Zu diesem Zweck würde ich einen Akka-Schauspieler verwenden. Im Gegensatz zum For-Understanding schlägt es fehl, sobald eine der Futures versagt, und ist daher in diesem Sinne etwas effizienter.
Erstellen Sie dann den Akteur, senden Sie ihm eine Nachricht (damit er weiß, wohin er seine Antwort senden soll) und warten Sie auf eine Antwort.
quelle
Diese Frage wurde beantwortet, aber ich veröffentliche meine Wertklassenlösung (Wertklassen wurden in 2.10 hinzugefügt), da hier keine vorhanden ist. Bitte zögern Sie nicht zu kritisieren.
ConcurrentFuture ist ein Future-Wrapper ohne Overhead, der die Standard-Future-Map / FlatMap von Do-this-then-that in Combine-All-and-Fail-If-Any-Fail ändert. Verwendung:
Im obigen Beispiel werden f1, f2 und f3 gleichzeitig ausgeführt, und wenn ein Fehler in einer beliebigen Reihenfolge auftritt, schlägt die Zukunft des Tupels sofort fehl.
quelle
Vielleicht möchten Sie die Future API von Twitter überprüfen. Insbesondere die Future.collect-Methode. Es macht genau das, was Sie wollen: https://twitter.github.io/scala_school/finagle.html
Der Quellcode Future.scala ist hier verfügbar: https://github.com/twitter/util/blob/master/util-core/src/main/scala/com/twitter/util/Future.scala
quelle
Sie können dies verwenden:
quelle