Chcę przeprowadzić obsługę błędów w mojej aplikacji internetowej scala.Obsługa błędów Scala: Future For Comprehension
Moja aplikacja rozmawia z bazą danych, aby pobrać kilka wierszy, następuje następujący przepływ.
- Pierwsze zaproszenie do db pobrać jakieś dane
- wykorzystywać dane w pierwszym zaproszeniu do pobierania innych danych z db
- Formularz odpowiedzi na podstawie danych otrzymanych od dwóch ostatnich połączeń DB.
Poniżej znajduje się mój pseudokod.
def getResponse(name: String)
(implicit ctxt: ExecutionContext): Future[Response] = {
for {
future1 <- callFuture1(name)
future2 <- callFuture2(future1.data)
future3 <- callFuture3(future1.data, future2.data)
} yield future3
}
Każda metoda w powyższym rozumieniu zwraca przyszłość, sygnatura tych metod jest przedstawiona poniżej.
private def callFuture1(name: String)
(implicit ctxt: ExecutionContext): Future[SomeType1] {...}
private def callFuture2(keywords: List[String])
(implicit ctxt: ExecutionContext): Future[SomeType2] {...}
private def callFuture3(data: List[SomeType3], counts: List[Int])
(implicit ctxt: ExecutionContext): Future[Response] {...}
Jak zrobię obsługi błędów/awarii, w następującej sytuacji
- Kiedy callFuture1 nie trafia do pobierania danych z bazy danych. Chcę zwrócić odpowiednią odpowiedź o błędzie z komunikatem o błędzie. Ponieważ callFuture2 zostaje wykonany dopiero po wywołaniu callFuture1. Nie chcę, aby wykonać wywołanie callFuture2, jeśli callFuture1 nie powiodło się/błąd i chciałby natychmiast zwrócić komunikat o błędzie . (To samo dla callFuture2 i callFuture3)
--edit--
Próbuję zwrócić właściwą odpowiedź błędu z getResponse() metoda, gdy którekolwiek z callFuture zawiedzie i nie przystąpić do kolejnego futureCalls.
Próbowałem następujących, na podstawie Peter Neyens odpowiedź, ale dał mi błąd runtime ..
def getResponse(name: String)
(implicit ctxt: ExecutionContext): Future[Response] = {
for {
future1 <- callFuture1(name) recoverWith {
case e:Exception => return Future{Response(Nil,Nil,e.getMessage)}
}
future2 <- callFuture2(future1.data)
future3 <- callFuture3(future1.data, future2.data)
} yield future3
}
Runtime error ja dostać
ERROR] [08/31/2015 02:09:45.011] [play-akka.actor.default-dispatcher-3] [ActorSystem(play)] Uncaught error from thread [play-akka.actor.default-dispatcher-3] (scala.runtime.NonLocalReturnControl)
[error] a.a.ActorSystemImpl - Uncaught error from thread [play-akka.actor.default-dispatcher-3]
scala.runtime.NonLocalReturnControl: null
Dzięki za tę odpowiedź. to było pomocne. nadal nie jestem pewien, czy to rozwiąże mój problem. 1) Korzystając z podejścia 1, (bez użycia domyślnej klasy), po odzyskaniu Future.failed (new Exception()), zgłoszony wyjątek i moje wykonanie nie jest kontynuowane. Próbuję zwrócić odpowiednią wartość ResponseMessage, gdy któraś z przyszłych awarii nie powiedzie się, bez przechodzenia do kolejnych przyszłych kroków (zaktualizuję to pytanie, aby było bardziej zrozumiałe) – konquestor
Future.fail (nowy wyjątek (...)) powoduje wykonanie rzutu wyjątek. Zamiast tego chcę Zwrócić odpowiedni komunikat o błędzie, gdy coś nie powiedzie się/błędy w przyszłości. – konquestor
Spróbuj czegoś podobnego do ostatniego przykładu kodu w mojej odpowiedzi. –