ZIO:为什么我得到 'An unchecked error was produced.'
ZIO: Why I get 'An unchecked error was produced.'
我对 ZIO 中的异常处理有误解。我关注了ZIO-Documentation.
在测试中class我运行以下代码:
new DefaultRuntime {}.unsafeRun(
(for {
peopleRef <- Ref.make(Vector(People()))
_ <- people(2).provide(Test(peopleRef)) // this throws the exception
} yield ())
.fold(
err =>
err shouldBe ServiceException("No People with id 2"),
_ => fail("line above should fail")
)
)
我想用 fold
函数我可以处理这个异常,但它甚至没有到达那里。我在控制台上收到此异常:
Fiber failed.
An unchecked error was produced.
pme123.zio.examples.swapi.package$ServiceException
at pme123.zio.examples.swapi.Swapi$Test$$anon.$anonfun$people(Swapi.scala:57)
at zio.ZIO$MapFn.apply(ZIO.scala:2590)
at zio.ZIO$MapFn.apply(ZIO.scala:2588)
at zio.internal.FiberContext.evaluateNow(FiberContext.scala:709)
at zio.Runtime.unsafeRunAsync(Runtime.scala:93)
....
我错过了什么?
这是一个最小的例子:
object MyApp
extends App {
def run(args: List[String]): ZIO[Environment, Nothing, Int] =
program
.fold({ error => 1 // this is not reached
}, _ => 0)
private lazy val program = for {
peopleRef <- Ref.make(Vector(22))
_ <- Test(peopleRef).people(12)
} yield ()
case class Test(ref: Ref[Vector[Int]]) {
def people(id: Int): Task[Int] =
for {
ints <- ref.get
} yield ints.find(_ == id) match {
case None => throw new IllegalArgumentException(s"No People with id $id") // this is thrown
case Some(p) => p
}
}
}
完整代码如下:SwapiTest.scala
ZIO 不会捕获异常,除非您将其包装在 ZIO
中。您可以使用 ZIO.effect
来包装整个抛出异常的遗留不安全代码块,或者只使用 IO.fail
来处理特定异常。
我将您的代码重构为更像 ZIO 并生成失败 Task
而不是抛出异常:
case class Test(ref: Ref[Vector[Int]]) {
def people(id: Int):Task[Int]=
for {
ints <- ref.get
int <- ZIO.effectTotal(ints.find(_ == id))
res <- int match {
case None => IO.fail(new IllegalArgumentException(s"No People with id $id"))
case Some(p) => ZIO.effectTotal(p)
}
} yield res
}
为了赶上 IllegalArgumentException
你需要以下折叠:
...
.fold(
err => err shouldBe IllegalArgumentException("No People with id 2"),
_ => fail("line above should fail")
)
ServiceException
不应该出现在这里,因为什么都没有扔。
我对 ZIO 中的异常处理有误解。我关注了ZIO-Documentation.
在测试中class我运行以下代码:
new DefaultRuntime {}.unsafeRun(
(for {
peopleRef <- Ref.make(Vector(People()))
_ <- people(2).provide(Test(peopleRef)) // this throws the exception
} yield ())
.fold(
err =>
err shouldBe ServiceException("No People with id 2"),
_ => fail("line above should fail")
)
)
我想用 fold
函数我可以处理这个异常,但它甚至没有到达那里。我在控制台上收到此异常:
Fiber failed.
An unchecked error was produced.
pme123.zio.examples.swapi.package$ServiceException
at pme123.zio.examples.swapi.Swapi$Test$$anon.$anonfun$people(Swapi.scala:57)
at zio.ZIO$MapFn.apply(ZIO.scala:2590)
at zio.ZIO$MapFn.apply(ZIO.scala:2588)
at zio.internal.FiberContext.evaluateNow(FiberContext.scala:709)
at zio.Runtime.unsafeRunAsync(Runtime.scala:93)
....
我错过了什么?
这是一个最小的例子:
object MyApp
extends App {
def run(args: List[String]): ZIO[Environment, Nothing, Int] =
program
.fold({ error => 1 // this is not reached
}, _ => 0)
private lazy val program = for {
peopleRef <- Ref.make(Vector(22))
_ <- Test(peopleRef).people(12)
} yield ()
case class Test(ref: Ref[Vector[Int]]) {
def people(id: Int): Task[Int] =
for {
ints <- ref.get
} yield ints.find(_ == id) match {
case None => throw new IllegalArgumentException(s"No People with id $id") // this is thrown
case Some(p) => p
}
}
}
完整代码如下:SwapiTest.scala
ZIO 不会捕获异常,除非您将其包装在 ZIO
中。您可以使用 ZIO.effect
来包装整个抛出异常的遗留不安全代码块,或者只使用 IO.fail
来处理特定异常。
我将您的代码重构为更像 ZIO 并生成失败 Task
而不是抛出异常:
case class Test(ref: Ref[Vector[Int]]) {
def people(id: Int):Task[Int]=
for {
ints <- ref.get
int <- ZIO.effectTotal(ints.find(_ == id))
res <- int match {
case None => IO.fail(new IllegalArgumentException(s"No People with id $id"))
case Some(p) => ZIO.effectTotal(p)
}
} yield res
}
为了赶上 IllegalArgumentException
你需要以下折叠:
...
.fold(
err => err shouldBe IllegalArgumentException("No People with id 2"),
_ => fail("line above should fail")
)
ServiceException
不应该出现在这里,因为什么都没有扔。