即使一个程序遇到错误,parMapN也会完成

时间:2019-03-12 22:17:22

标签: scala scala-cats io-monad

使用parMapN,可以并行执行多个IO,如下所示:

import cats.implicits._
import cats.effect.{ContextShift, IO}
import scala.concurrent.ExecutionContext

implicit val cs: ContextShift[IO] = IO.contextShift(ExecutionContext.global)

val ioA = IO(for(i <- 1 to 100) { println(s"A$i"); Thread.sleep(100) })
val ioB = IO(for(i <- 1 to 100) { println(s"B$i"); Thread.sleep(100) })
val ioC = IO(for(i <- 1 to 100) { println(s"C$i"); Thread.sleep(100) })

val program = (ioA, ioB, ioC).parMapN { (_, _, _) => () }

program.unsafeRunSync()

示例输出:

A1
C1
B1
A2
C2
B2
A3
C3
B3
A4
C4
B4
A5
B5
C5
A6
B6
C6
A7
B7
C7
A8
...

根据documentation,如果IO中的任何一个失败完成,则未完成的任务将被取消。更改此机制以使所有IO都完成的最佳方法是什么?

在我的情况下,某些IO不返回任何内容(IO[Unit]),并且我仍然想确保一切正常运行,直到完成或遇到错误为止。

2 个答案:

答案 0 :(得分:1)

好吧,我在发布问题后不久找到了一个可能的答案。不知道这是否是处理此问题的最佳方法,但是像这样定义我的IO对我来说有用:

val ioA = IO(for(i <- 1 to 100) { println(s"A$i"); Thread.sleep(100) }).attempt
val ioB = IO(for(i <- 1 to 100) { println(s"B$i"); Thread.sleep(100) }).attempt
val ioC = IO(for(i <- 1 to 100) { println(s"C$i"); Thread.sleep(100) }).attempt

答案 1 :(得分:0)

据我所知,您的示例代码没有任何错误。 所以你应该有一个像下面这样的代码才能看到这个功能:

val ioA = IO(for(i <- 1 to 100) { println(s"A$i"); Thread.sleep(100) })
val ioB = IO.raiseError[Unit](new Exception("boom"))
val ioC = IO(for(i <- 1 to 100) { println(s"C$i"); Thread.sleep(100) })

看起来也不太好,因为 attempt 函数会将内部结构更改为 IO[Either[_,_]],这不符合您的意图,是吗?