#scala #future #reactive-programming
#скала #будущее #реактивное программирование
Вопрос:
Допустим, я использую асинхронную библиотеку для чтения и записи данных. В случае сбоя я получаю сообщение об ошибке в виде строки, в противном случае — данные. Есть ли лучший способ представить возвращаемый тип, чем Future[Either[String, Future[Data]]]
?
Возможная реализация:
def createData(name: String): Future[Either[String, Future[Data]]] = {
dataDAO.findOneByName(name).flatMap {
case Some(data) =>
Future.successful(Left(s"Data with name already exists. $name"))
case None =>
val data = Data.createFromName(name)
dataDAO.save(data).map {
lastError =>
data
}.right.futureSuccessful
}
}
Комментарии:
1. Зачем использовать
Future[Either[String, Future[Data]]]
вместоFuture[Either[String, Data]]
?2. Почему бы не обернуть сообщение об ошибке в исключение и использовать
Future.failed
?3. @izstas я думаю, что использование исключения здесь было бы плохим. Вы не должны использовать исключения для «бизнес-ошибок», а уже существующая запись — это полностью ожидаемый сценарий, поэтому это не «исключение». Использование either в качестве возвращаемого типа делает подпись намного более понятной и подробной для потребителя.
Ответ №1:
Ваш возвращаемый тип должен быть Future[Either[String, Data]]
Чтобы заархивировать это, вам нужно изменить свой второй случай на:
case None =>
val data = Data.createFromName(name)
dataDAO.save(data).map {
_ => Right(data)
}
Я бы даже улучшил ваш тип ошибки с String
на , например CreateDataError
, так, чтобы ваш возвращаемый тип был Future[Either[CreateDataError, Data]]
бы, и ваш первый случай был бы
// Having somewhere decalred
trait CreateDataError
object DataAlreadyExistsError
//...
//...
case Some(data) =>
Future.successful(Left(DataAlreadyExistsError))
Комментарии:
1. Спасибо! Очевидно, я упустил из виду это будущее / любую комбинацию.