2017-12-19 7 views
0

ich Akka myActor1 verwenden wie unten eine andere myActor2 für eine zukünftige Antwort zu fragen:Wie Objekt in einer Zukunft in Scala erhalten

val future = myActor2 ? request 
val result = Await.result(future, timeout.duration).asInstanceOf[Person] 

lassen Sie uns sagen Ergebnis ein Fall Klasse ist wie folgt:

case class Person(name: String, age: Int) 

Ich möchte den Prozess nicht blockieren, also wähle ich nicht Await.result zu verwenden. So habe ich den folgenden Code:

val future = (myActor2 ? request).mapTo[Person] 

jetzt ist Zukunft Zukunft [Person] und keine Zukunft [Alle]. Wie kann ich dann die in der Zukunft enthaltene Person extrahieren und Ausnahme behandeln? Ich habe etwas mit onComplete versucht, aber Erfolg scheint nur Int und nicht Person zu akzeptieren. Ich möchte etwas wie unten:

future onComplete { 
    case Success(result) => result 
    case Failure(failure => doSomethingOnFailure(failure) 
} 

Haben Sie eine Idee?

+1

Wenn Sie zwischen zwei Schauspielern kommunizieren, sollten Sie niemals eine Frage stellen. Verwenden Sie eine Tell und hören Sie sich eine Antwort an. –

+1

Haben Sie die Funktion 'pipe' überprüft? https://doc.akka.io/docs/akka/current/actors.html?language=scala#ask-send-and-receive-future – mfirry

+2

Sie können und sollten keinen Wert aus einem monadischen Kontext extrahieren, sondern darin verfassen. – cchantep

Antwort

1

Sie möchten, dass die Verarbeitung der Antwort durch Verarbeitung einer anderen Nachricht erfolgt. Wenn Sie mit der Antwort des anderen Akteurs eine Nachricht in Betracht ziehen, reicht es aus, die Anfrage einfach mit tell (!) zu senden und der Empfangs-Methode für die Antwort einen Fall hinzuzufügen.

Wenn Sie vermeiden möchten, dass parallele Anfragen und Antworten verwirrend sind, können Sie become und Stash verwenden, um sicherzustellen, dass nur eine Anfrage gleichzeitig ausgeführt werden kann. Beachten Sie, dass dies den Durchsatz Ihres Systems natürlich begrenzt.

Wenn Sie irgendwie wollen ‚übersetzen‘ die Antwort, bevor es an receive Handler vorbei, das pipe Muster könnte sich als nützlich erweisen:

import akka.pattern.pipe 

... 
    val someIdentifier = ??? 
    (myActor2 ? request) 
     .map(response => MyCommandWith(response, someIdentifier)) 
     .pipeTo(self) 

Dies wird das Ergebnis der ask, wo es sich sammeln und dann schicken es als eine Nachricht an den aktuellen Schauspieler (self). Seien Sie sehr vorsichtig, aber schließen Sie in der Kartenfunktion keinen Akteursstatus!

Wenn Sie weiteres Ergebnis oder Fehlerbehandlung soll durch den ursprünglichen Absender der Nachricht zu tun, brauchen Sie gar nicht pipe aber Sie forward statt ask nutzen könnten.

0

Es gibt keine Magie, Future[Person] in Person zu konvertieren. Sie müssen entweder Await in dieser Zukunft aufrufen, um das Ergebnis zu extrahieren oder dieses Stück Code Future[Smth] zurückgeben und Extraktion des Ergebnisses an einen Aufrufer delegieren.

Verwandte Themen