本章节探讨使用 ZIO 来管理资源的通常的方法。
ZIO的资源管理功能包含了同步,异步,并发和其他 effect 类型,即使在应用程序出现故障,中断或缺陷的情况下,也能提供有力的保证。
Finalizing
通过 ZIO#ensuring
方法,ZIO 提供了类似 try
/ finally
的机制。
类似于 try
/ finally
一样, ensuring
函数可确保“终结器(finalizer)”将在一个 effect 开始执行然后终止(无论出于何种原因)后开始执行。
val finalizer =
UIO.effectTotal(println("Finalizing!"))
// finalizer: UIO[Unit] = zio.ZIO$EffectTotal@4ffbaf7e
val finalized: IO[String, Unit] =
IO.fail("Failed!").ensuring(finalizer)
// finalized: IO[String, Unit] = zio.ZIO$CheckInterrupt@4f16a3db
终结器是不允许失败的,这意味着它必须在内部处理所有的错误。
和 try
/ finally
一样,终结器可以嵌套,并且任何来自内部终结器的错误不会影响到它的外部终结器。嵌套终结器的执行顺序是反向,并且线性的(不是并行的)。
和 try
/ finally
不同的是,ensuring
可以工作于所有的 effect 类型,包括异步和并发 effect。
Bracket
通常 try
/ finally
被用于安全地获取和释放资源,例如一个新的 socket 的连接或一个文件的打开:
val handle = openFile(name)
try {
processFile(handle)
} finally closeFile(handle)
ZIO 将这种通用模式封装在 ZIO#bracket
中,它允许您自动一个acquire effect 用于获取资源;一个 release effect 用于释放它;和一个 use effect 用于使用资源。
运行时系统将保证 release effect 的执行,哪怕存在错误或中断。
val groupedFileData: IO[IOException, Unit] =
openFile("data.json").bracket(closeFile(_)) { file =>
for {
data <- decodeData(file)
grouped <- groupData(data)
} yield grouped
}
和 ensuring
一样,brackets 具有语意成分,所以如果一个 bracket 嵌套在另一个 bracket 里面,那么当外部 bracket 获取资源的时候,也就意味着这个外部 bracket’s 的 release 函数也将会被执行,无论它的内嵌 bracket 的释放失败与否。
Next Steps
如果您对资源处理感到满意,那么下一步就是学习基本并发处理。