【问题标题】:Better way to handle errors with Monix Observable使用 Monix Observable 处理错误的更好方法
【发布时间】:2019-04-10 13:43:50
【问题描述】:

我正在尝试使用 monix 3.0.0-RC1 构建反应式应用程序。

例如 a 有一个 Int 的 Seq,而第二个元素是错误的。我可以使用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(...)在每一步都不爽。

处理错误的更好方法是什么?

【问题讨论】:

  • 异常并不是真正的“抛出”。它作为 Observable 错误设计的一部分在错误通道上发送。你为什么不喜欢它?您不想在每一步都处理它的事实暗示它应该像第一个示例一样完成。
  • 正如@AlvaroCarrasco 所说,Exception 永远不会被抛出,您的第一个示例是使用 Observables,因为它们被使用。

标签: scala observable monix


【解决方案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】:

    如果你想drop坏元素,你可以这样做。

    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将Task组合变成Task[Either]。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-27
      • 1970-01-01
      • 1970-01-01
      • 2018-10-26
      • 1970-01-01
      相关资源
      最近更新 更多