0Pricing
Scala for Backend Engineering & Functional Programming · 课时

错误通道与依赖通道

类型化错误与环境

错误通道与依赖通道 是 CoddyKit 上的免费 Scala for Backend Engineering & Functional Programming 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Scala for Backend Engineering & Functional Programming 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Scala for Backend Engineering & Functional Programming 课程共包含 4 节课。

两个强大的通道

除了成功值之外,ZIO[R, E, A] 还会跟踪类型化错误通道 E 和依赖通道 R。两者都会显示在类型中,因此失败情况和需求在编译时就是明确的。

类型化错误

将领域故障建模为一个密封层次结构,并将其放入 E 中。这样,编译器就会强制您恰好处理这些情况。

import zio._

sealed trait AppError
case object NotFound extends AppError
case object Forbidden extends AppError

val lookup: IO[AppError, String] = ZIO.fail(NotFound)

使用 catchAll 恢复

catchAll 会通过提供一个新的效果来处理 E 中的所有错误。处理完成后,如果所有错误都已处理,错误通道可以变为 Nothing。

import zio._

val safe: UIO[String] =
  ZIO.fail("boom").catchAll(e => ZIO.succeed(s"recovered: $e"))

catchSome 与 orElse

catchSome 只恢复匹配的错误。orElse 会在发生任何失败时回退到另一个效果。

import zio._

val prog = ZIO.fail("x").orElse(ZIO.succeed("fallback"))

Either 与 fold

either 会将 ZIO[R, E, A] 转换为 ZIO[R, Nothing, Either[E, A]]。fold 会将错误和成功统一处理为一个值。

import zio._

val label: UIO[String] =
  ZIO.fail(404).fold(e => s"err $e", v => s"ok $v")

缺陷与失败

ZIO 将失败(有类型、可预期,位于 E 中)与缺陷(意外抛出的异常)区分开来。ZIO.die 会引发缺陷;缺陷不属于 E 类型,而是表示程序错误。

环境 R

R 通道声明一个效果所需的服务。使用 ZIO.service 访问服务;在提供服务之前,该需求会一直出现在 R 中。

import zio._

trait Logger { def log(s: String): UIO[Unit] }

val prog: ZIO[Logger, Nothing, Unit] =
  ZIO.serviceWithZIO[Logger](_.log("hello"))

定义服务

服务由一个特征和一个用于构建它的 ZLayer 组成。层描述如何构造依赖,并且自身也可以依赖其他层。

import zio._

case class ConsoleLogger() extends Logger {
  def log(s: String): UIO[Unit] = ZIO.succeed(println(s))
}
object ConsoleLogger {
  val layer: ULayer[Logger] = ZLayer.succeed(ConsoleLogger())
}

trait Logger { def log(s: String): UIO[Unit] }

提供依赖

provide(或 provideLayer)会满足 R 中的需求,将 ZIO[Logger, E, A] 转换为可以运行的 ZIO[Any, E, A]。

import zio._

val runnable: UIO[Unit] =
  ZIO.serviceWithZIO[Logger](_.log("hi"))
    .provide(ConsoleLogger.layer)

trait Logger { def log(s: String): UIO[Unit] }
object ConsoleLogger { val layer: ULayer[Logger] = ??? }

组合层

层可以使用 ++(组合)进行水平组合,也可以使用 >>>(将一层的输出作为另一层的输入)进行垂直组合,从而构建完整的依赖图。

import zio._

// val appLayer = configLayer ++ (dbLayer >>> repoLayer)

普通 Scala 基线实现

作为对比,这是一个手动处理错误的自包含 Scala 程序。ZIO 会在类型中编码相同的错误,并通过层注入依赖。

object Main {
  def main(args: Array[String]): Unit = {
    val result: Either[String, Int] = Left("NotFound")
    val msg = result.fold(e => s"err $e", v => s"ok $v")
    println(msg)
  }
}

快速检查

provide 方法会对 ZIO[Logger, E, A] 做什么?

回顾

您处理了两个额外的通道:

  • 错误:类型化的 E、catchAll、orElse、fold,以及缺陷与失败的区别
  • 依赖:R、服务、ZLayer、provide 和层组合

下一步:运行 ZIO 应用。

常见问题解答

「错误通道与依赖通道」课时是免费的吗?

是的 — 「错误通道与依赖通道」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Scala for Backend Engineering & Functional Programming 课程的其余内容,请升级到 CoddyKit PRO。 Scala for Backend Engineering & Functional Programming 课程共包含 4 节课。

「错误通道与依赖通道」这节课中我会学到什么?

类型化错误与环境 你通过在浏览器中直接运行的动手代码来练习 Scala for Backend Engineering & Functional Programming,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Scala for Backend Engineering & Functional Programming 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Scala for Backend Engineering & Functional Programming 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「错误通道与依赖通道」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Scala for Backend Engineering & Functional Programming 课中编写并运行代码吗?

能。每节 Scala for Backend Engineering & Functional Programming 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. ZIO 效果
  2. 组合 ZIO
  3. 错误通道与依赖通道
  4. 运行 ZIO 应用
← 返回 Scala for Backend Engineering & Functional Programming