트위터의 Future.rescure 함수가 마음에 들 때가 있다. (간결함이 좋다..)
https://twitter.github.io/util/docs/com/twitter/util/Future.html를 참조하면. 예외가 발생할 때 새로운 결과로 이어지게 한다. 코드가 간결해 진다.
def rescue[B >: A](rescueException: PartialFunction[Throwable, Future[B]]): Future[B]
If this, the original future, results in an exceptional computation, rescueException may convert the failure into a new result.
import com.twitter.util.{Await, Future} val f1: Future[Int] = Future.exception(new Exception("boom1!")) val f2: Future[Int] = Future.exception(new Exception("boom2!")) val newf: Future[Int] => Future[Int] = x => x.rescue { case e: Exception if e.getMessage == "boom1!" => Future.value(1) } Await.result(newf(f1)) // 1 Await.result(newf(f2)) // throws java.lang.Exception: boom2!
실제 예.
def getToken : Future[Option[FacebookToken]] = {
val request = GetRequest(s"/oauth/access_token?client_id=$apiKey&client_secret=$apiSecret&grant_type=client_credentials",
"graph.facebook.com", true)
perform(request) flatMap { token =>
token.status match {
case Ok => Future(Option(fromJson[FacebookToken](token.contentString)))
case _ => Future(Option.empty)
}
} rescue { case _ => Future(Option.empty)}
}
자바의 Future에는 rescue대신 exceptionally가 있다. 예쁘지 않다...
AtomicBoolean thenAcceptCalled = new AtomicBoolean(false);
AtomicBoolean exceptionallyCalled = new AtomicBoolean(false);
CompletableFuture<String> future = new CompletableFuture<>();
future.thenAccept(value -> {
thenAcceptCalled.set(true);
}).exceptionally(throwable -> {
exceptionallyCalled.set(true);
return null;
});
future.completeExceptionally(new RuntimeException());
assertThat(thenAcceptCalled.get(), is(false));
assertThat(exceptionallyCalled.get(), is(true));