scala - 如何运行不阻塞主线程但在主线程失败时抛出异常的异步 IO 操作?

标签 scala scala-cats

我正在调查 Cats 以完成上述任务。我试着写下面的例子

  1. 运行不阻塞主线程的 IO 操作
  2. 如果失败则在主线程中抛出异常
import cats.effect.{IO, Async}

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future

val apiCall = Future.successful("I come from the Future!")

val ioa: IO[String] =
  Async[IO].async { cb =>
    import scala.util.{Failure, Success}
    Thread.sleep(1000)
    throw new RuntimeException

    apiCall.onComplete {
      case Success(value) => cb(Right(value))
      case Failure(error) => cb(Left(error))
    }
 }

ioa.unsafeRunAsync(result => result match {
    case Left(result) => throw result
    case Right(_) =>
})

然而,它似乎在这两方面都失败了。它阻塞主线程,只在子线程中抛出异常。我尝试做的事情可行吗?

最佳答案

你可以这样做:

val longRunningOperation: IO[Unit] = ...
val app: IO[Unit] = ...

val program: IO[Unit] =
  IO.racePair(app, longRunningOperation).flatMap {
    case Left((_, fiberLongRunning)) =>  fiberLongRunning.cancel.void
    case Right((fiberApp, _)) => fiberApp.join.void
  }

override def run(args: List[String]): IO[ExitCode] =
  program.as(ExitCode.Success)

racePair 将同时运行两个 IO,如果其中一个失败,则它将取消另一个。
现在,如果 longRunningOperation 没有错误地完成,那么等待 app;但是,如果 app 是第一个完成的,那么我决定取消 longRunningOperation (你当然可以,改变那个)


感谢 Adam Rosien 指出,如果您想在这两种情况下加入,那么最好是:

val program: IO[Unit] = (app, longRunningOperation).parTupled.void

您可以看到代码正在运行并使用它 here

关于scala - 如何运行不阻塞主线程但在主线程失败时抛出异常的异步 IO 操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64883178/

相关文章:

python - 获取保存 Parquet 文件的默认 HDFS 路径

scala - 有没有办法用sbt-onejar在同一个SBT项目中自动打包多个主类?

scala - 固定列表元素以定位在 Scala 中的合并列表中

eclipse - Scala akka - 无法从 Maven 构建的 jar-with-dependency 运行程序

scala - 使用 mapN 验证的猫

scala - 如何 flatMap cats Applicatives

list - Scala - 将元组映射到 map 的 map ?

scala - 在使用 scala 的版本化配置的情况下,如何将解析与验证分开?

scala - 类型级 Cats.Effect 与类型级 eff。哪个,为什么?

scala - 更改 fs2.Stream 的效果类型