已发布 上游基线 bf46254 原文 ↗ 在 GitHub 编辑

沙箱化

掌握 Effect 中的沙箱化错误处理,从而详细检查并恢复失败、defect 与中断。

错误是编程中不可避免的一部分,它们可能来自各种来源,例如失败(failure)、defect、Fiber 中断,或者这些情况的组合。本指南讲解如何使用 Effect.sandbox 函数来隔离并理解基于 Effect 的代码中错误的成因。

sandbox / unsandbox

Effect.sandbox 函数允许你把一个 effect 中所有可能的错误成因封装起来。它会暴露一个 effect 的完整 cause,无论其成因是失败、defect、Fiber 中断,还是这些因素的组合。

简单来说,它接收一个 effect Effect<A, E, R>,并将其转换为一个 effect Effect<A, Cause<E>, R>,此时错误通道中包含着错误的详细成因(cause)。

语法

Effect<A, E, R> -> Effect<A, Cause<E>, R>

通过使用 Effect.sandbox 函数,你就能访问异常 effect 的底层成因。这些成因以 Cause<E> 类型表示,并且可以在 Effect 数据类型的错误通道中获取。

一旦暴露了这些成因,你就可以利用标准的错误处理操作符,例如 Effect.catchAllEffect.catchTags,来更有效地处理错误。这些操作符让你能够针对特定的错误条件做出响应。

如果需要,我们可以用 Effect.unsandbox 撤销沙箱化操作。

示例(处理不同的错误成因)

import { Effect, Console } from "effect"

//      ┌─── Effect<string, Error, never>
//      ▼
const task = Effect.fail(new Error("Oh uh!")).pipe(Effect.as("primary result"))

//      ┌─── Effect<string, Cause<Error>, never>
//      ▼
const sandboxed = Effect.sandbox(task)

const program = Effect.catchTags(sandboxed, {
  Die: (cause) =>
    Console.log(`Caught a defect: ${cause.defect}`).pipe(
      Effect.as("fallback result on defect"),
    ),
  Interrupt: (cause) =>
    Console.log(`Caught a defect: ${cause.fiberId}`).pipe(
      Effect.as("fallback result on fiber interruption"),
    ),
  Fail: (cause) =>
    Console.log(`Caught a defect: ${cause.error}`).pipe(
      Effect.as("fallback result on failure"),
    ),
})

// Restore the original error handling with unsandbox
const main = Effect.unsandbox(program)

Effect.runPromise(main).then(console.log)
/*
Output:
Caught a defect: Oh uh!
fallback result on failure
*/