2016-10-06 9 views
7

Jak sobie z tym poradzić, jeśli w przyszłości zwrócony zostanie nieudany wyjątek?Kontynuuj, gdy Future.failed (nowy wyjątek ("")) zostanie zwrócony w Scali

Scenariusz jest, że mój kod wywołuje getValue(), odwzorowuje wynik verifyValue() a następnie chcę, aby móc obsłużyć przypadek, gdy wynik getValue() jest Future.failed(new Exception("message")). Jednak gdy uruchomię to, jeśli wynik getValue() jest nieudaną przyszłością, po prostu wyrzuca wyjątek zamiast go obsługiwać.

Czy ktoś ma jakieś sugestie, w jaki sposób to zrobić?

def method(): Future[JsObject] = { 
    getValue().flatMap(verifyValue(_)) 
} 

def getValue(): Future[JsObject] = { 
    try { 
     value1 <- getValue1() 
     value2 <- getValue2(value1) 
    } yield { 
     value2 
    } 
} 

def verifyValue(result: Any): Future[JsObject] = { 
    result match { 
    case e: Exception => 
     getValue() 
    case json: JsObject => Future.successful(json) 
    } 
} 

Aktualizacja: nie sądzę, ja to jasno z pierwotnego pytania, ale dlatego, że flatmap wartości jest to, że nie chcę, aby jawnie trzeba czekać na którykolwiek z kontraktami w mój kod, a więc nie chcę używać Future.onComplete {} do rozwiązania tej wartości.

Aktualizacja 2: Kolejną rzeczą, która może nie być jasna, jest to, że jeśli zgłasza wyjątek, chcę wywołać inną metodę. Nie chcę, aby po prostu obsługiwał wyjątek, będzie rejestrował wyjątek, a następnie wywoływał inną metodę, której wartość zwracana jest tego samego typu co getValue().

Odpowiedz

3

Co skończyło się robi jest przy użyciu metody Future.fallbackTo().

def method(): Future[JsObject] = { 
    getValue().fallbackTo(method1()).fallbackTo(method2()).fallbackTo(method3()) 
} 

Jeśli przyszłość z pierwszego getValue() nie powiedzie, będzie to nazwać method1(). Jeśli to również się nie powiedzie, zadzwoni pod numer method2() itd. Jeśli jedna z metod się powiedzie, zwróci tę wartość. Jeśli żadna z metod nie powiedzie się, zwróci ona nieudaną przyszłość z getValue().

To rozwiązanie nie jest idealne, ponieważ chciałbym, aby wszystkie cztery wyjątki zostały odrzucone, jeśli wszystkie próby się nie powiedzie, ale przynajmniej pozwala mi ponownie spróbować metody getValue().

+1

Brzmi tak, jak chcesz http://johnkurkowski.com/posts/accumulating-multiple-failures-in-a-ValidationNEL/ – Yawar

+0

Brzmi niewiarygodnie! – annedroiid

+0

Dzięki, ale jestem zbyt leniwy, aby napisać odpowiedź godną nagrody, a także post robi całkiem dobrą robotę wyjaśniając pojęcia :-) – Yawar

6

Używaj recover lub recoverWith

odzyskać lub recoverWith nazywane są po przyszłość kończy się niepowodzeniem z wyjątkiem. W bloku odzyskiwania możesz podać alternatywną wartość.

recoverWith przeciwieństwie recover bierze przyszłość czegoś

getValue().recover { case th => 
    //based on the exception type do something here 
    defaultValue //returning some default value on failure 
} 
+0

Jeśli próbuję to zrobić, getValue2 (wartość1) ma błąd kompilacji "niezgodności typu, oczekiwane: String, actual: Object", mimo że w odzyskiwaniu po prostu ponownie wywołuję getValue(). – annedroiid

+0

Proszę przerwać upvoting to. To nie działa, odzyskiwanie i odzyskiwanie z metodami obsługują tylko wyjątek, nie można wywołać innej metody, która mogłaby powrócić z wartością sukcesu, który jest moim celem. – annedroiid

+0

@annedroiid - czy możesz podać w swoim pytaniu co najmniej sygnatury wszystkich odpowiednich metod i dokładny komunikat o błędzie, który otrzymujesz? Btw, 'recover' i' recoverWith' całkiem wyraźnie pozwalają ci obliczyć i zwrócić udaną wartość. Zobacz http://www.scala-lang.org/api/current/index.html#scala.concurrent.Future @ recover [U>: T] (pf: PartialFunction [Throwable, U]) (implicitexecutor: scala.concurrent.ExecutionContext): scala.concurrent.Future [U] – Yawar

Powiązane problemy