Это вопрос вкуса в основном. Я обычно конвертировать Future[HttpResponse]
в Future[Try[HttpResponse]]
, а затем обработать его как
response.flatMap { tryResp =>
tryResp match {
case Success(res) =>
res.status match {
case OK =>
// Unmarshal response here into Future[Something]
case Found =>
// Handle redirect by calling requestBlhBlah() again with anotehr URI
case _ =>
// I got status code I didn't expect so I wrap it along with body into Future failure
Unmarshal(res.entity).to[String].flatMap { body =>
Future.failed(new IOException(s"The response status is ${res.status} [${request.uri}] and response body is $body"))
}
}
case Failure(ex) =>
Future.failed(ex)
}
}
Если вы используете клиент на основе потоков можно также указать Decider
для обработки ошибок
val decider: Decider = {
case ex =>
ex.printStackTrace()
Supervision.Stop // Passes error down to subscriber
}
, а затем использовать его в любом Materializer
implicit val materializer = ActorMaterializer(ActorMaterializerSettings(system).withSupervisionStrategy(decider))(system)
или в основе каждого потока с помощью .withAttributes(ActorAttributes.supervisionStrategy(decider))
По состоянию на Future
сбой. Возможно, вам решать, как с этим обращаться. Вы можете преобразовать отказ в что-то другое, используя recoverWith
или зарегистрировать его в Future.onFailure
.
Ahm ... Я как бы делаю то же самое, но с Либо вместо Try - конечный результат: если все в порядке, возвращается Future [Something], иначе неудавшееся будущее возвращается либо с исключением в исходный ответ (Future [HttpResponse]) или какое-либо исключение клиента, которое мы определяем для известного ответа об ошибке от целевой службы. – EugeneMi
Однако (1) Исключение, возвращаемое будущим, никогда не распространяется на супервизора и, следовательно, никогда не обрабатывается, (2) Мы должен знать, какие исключения клиент может вернуть, и либо обрабатывать, либо регистрировать их. – EugeneMi
Добавлен больше к моему ответу. – expert