你可以使用
Future.recoverWith
函数,如果
Future
失败。
val failed = Future.failed(new Exception("boom"))
failed recoverWith {
case e: Exception => Future.failed(new Exception("A prettier error message", e)
}
这将导致理解上稍显丑陋:
for {
future1 <- callFuture1(name) recoverWith {
case npe: NullPointerException =>
Future.failed(new Exception("how did this happen in Scala ?", npe))
case e: IllegalArgumentException =>
Future.failed(new Exception("better watch what you give me", e))
case t: Throwable =>
Future.failed(new Exception("pretty message A", t))
}
future2 <- callFuture2(future1.data) recoverWith {
case e: Exception => Future.failed(new Exception("pretty message B", e))
}
future3 <- callFuture3(future1.data, future2.data) recoverWith {
case e: Exception => Future.failed(new Exception("pretty message C", e))
}
} yield future3
请注意,您也可以定义自己的异常来代替
Exception
,如果您希望添加更多信息而不仅仅是错误消息。
如果不希望细粒度控制根据
Throwable
在失败的
将来
(与
callFuture1
),你可以丰富
将来
使用隐式类设置自定义错误消息稍微简单一些:
implicit class ErrorMessageFuture[A](val future: Future[A]) extends AnyVal {
def errorMsg(error: String): Future[A] = future.recoverWith {
case t: Throwable => Future.failed(new Exception(error, t))
}
}
您可以像这样使用:
for {
future1 <- callFuture1(name) errorMsg "pretty A"
future2 <- callFuture2(future1.data) errorMsg "pretty B"
future3 <- callFuture3(future1.data, future2.data) errorMsg "pretty C"
} yield future3
在这两种情况下,使用
errorMsg
或
recoverWith
直接来说,你仍然依赖
将来
,所以如果
将来
无法执行以下操作
Futures
将不会执行,您可以直接在失败的
将来
.
您没有指定如何处理错误消息。例如,如果希望使用错误消息创建不同的
Response
你可以使用
恢复方式
或
recover
.
future3 recover { case e: Exception =>
val errorMsg = e.getMessage
InternalServerError(errorMsg)
}