#scala #observable #monix
#scala #наблюдаемый #monix
Вопрос:
Я пытаюсь создать реактивное приложение с monix 3.0.0-RC1.
Например, у a есть последовательность значений Int, а второй элемент неверен. Я могу использовать Oservable.raiseError(...)
для обработки этого:
Observable.fromIterable(Seq(1,2,3))
.flatMap( i =>
if (i == 2) Observable.raiseError(new Exception("Wrong i"))
else Observable.pure(i)
)
.doOnNext(i => println(s"Processing $i"))
.foreachL(i => println(s"Finished $i"))
.onErrorHandle(_ => Task.unit)
Мне не нравится генерируемое исключение в приведенном выше коде.
С другой стороны, я могу использовать Scala Either
:
Observable.fromIterable(Seq(1,2,3))
.map( i =>
if (i == 2) Left("Wrong i")
else Right(i)
)
.doOnNext(either => either.map( i => println(s"Processing $i") ))
.foreachL(either => either.map( i => println(s"Finished $i") ))
Но either => either.map(...)
на каждом шаге не круто.
Какой лучший способ обработки ошибок?
Комментарии:
1. Исключение на самом деле не «выбрасывается». Он передается по каналу ошибок как часть дизайна Observable для ошибок. Почему вам это не нравится? Тот факт, что вы не хотите иметь дело с этим на каждом шаге, является намеком на то, что это должно быть сделано, как в первом примере.
2. Как сказал @AlvaroCarrasco,
Exception
никогда не выбрасывается, и ваш первый пример используетObservable
s, поскольку они улучшаются для использования.
Ответ №1:
Вы можете использовать collect
, если вас интересует только правильный результат, например
val logError = {
case Right(_) => Task.unit
case Left(i) => Task.delay(println(s"An error occured $i"))
}
Observable.fromIterable(Seq(1,2,3))
.map( i =>
if (i == 2) Left("Wrong i")
else Right(i)
)
.doOnNext(logError)
.collect {
case Right(value) => value
}
.foreachL(i => println(i))
Ответ №2:
Если вы хотите удалить плохой элемент, вы можете сделать это таким образом.
Observable.fromIterable(1 to 3)
.mapEval(p => { if(i == 2) Task.raiseError(new Exception)
else Task.now(i)
}.attempt )
.collect { case Right(v) => v }
.foreachL(println)
.runToFuture
/*
1
3
*/
В основном продолжайте использовать Task и attempt
превращать композицию задачи в задачу [Либо].