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

Exit

用 Exit 表示 Effect 工作流的运行结果,捕获成功值或失败原因。

一个 Exit<A, E> 描述了一次 Effect 工作流运行的结果。

Exit<A, E> 有两种可能的状态:

  • Exit.Success:包含类型为 A 的成功值。
  • Exit.Failure:包含类型为 E 的失败 Cause

创建 Exit

Exit 模块提供了两个用于构造 Exit 值的主要函数:Exit.succeedExit.failCause。 这两个函数分别以成功或失败的形式,表示一次 effectful 计算的结果。

succeed

Exit.succeed 创建一个表示成功结果的 Exit 值。 当你想表明一次计算成功完成,并提供其计算结果时,就可以使用这个函数。

示例(创建一个成功的 Exit)

import { Exit } from "effect"

// Create an Exit representing a successful outcome with the value 42
//
//      ┌─── Exit<number, never>
//      ▼
const successExit = Exit.succeed(42)

console.log(successExit)
successExit // => Exit.succeed(42)

failCause

Exit.failCause 创建一个表示失败的 Exit 值。 失败通过一个 Cause 对象来描述,该对象可以封装预期内的错误、defect、中断,甚至是复合错误。

示例(创建一个失败的 Exit)

import { Exit, Cause } from "effect"

// Create an Exit representing a failure with an error message
//
//      ┌─── Exit<never, string>
//      ▼
const failureExit = Exit.failCause(Cause.fail("Something went wrong"))

console.log(failureExit)
failureExit // => Exit.fail("Something went wrong")

模式匹配

你可以使用 Exit.match 函数处理 Exit 的不同结果。 该函数允许你提供两个独立的回调,分别处理一次 Effect 执行的成功与失败情况。

示例(同时匹配成功与失败状态)

import { Effect, Exit, Cause } from "effect"

//      ┌─── Exit<number, never>
//      ▼
const simulatedSuccess = Effect.runSyncExit(Effect.succeed(1))

console.log(
  Exit.match(simulatedSuccess, {
    onFailure: (cause) => `Exited with failure state: ${Cause.pretty(cause)}`,
    onSuccess: (value) => `Exited with success value: ${value}`,
  }),
)
Exit.match(simulatedSuccess, {
  onFailure: (cause) => `Exited with failure state: ${Cause.pretty(cause)}`,
  onSuccess: (value) => `Exited with success value: ${value}`,
}) // => "Exited with success value: 1"

//      ┌─── Exit<never, string>
//      ▼
const simulatedFailure = Effect.runSyncExit(
  Effect.failCause(Cause.fail("error")),
)

console.log(
  Exit.match(simulatedFailure, {
    onFailure: (cause) => `Exited with failure state: ${Cause.pretty(cause)}`,
    onSuccess: (value) => `Exited with success value: ${value}`,
  }),
)
/*
Output:
Exited with failure state: Error: error
    ...stack trace...
*/
Exit.match(simulatedFailure, {
  onFailure: (cause) => `Exited with failure state: ${Cause.pretty(cause)}`,
  onSuccess: (value) => `Exited with success value: ${value}`,
}).split("\n")[0] // => "Exited with failure state: Error: error"

Exit 与 Result 的对比

从概念上讲,Exit<A, E> 可以看作 Result<A, Cause<E>>。不过 Cause 类型所表示的并不只是类型为 E 的预期错误,它还包括:

  • 中断原因
  • Defect(非预期的错误)
  • 多个 Cause 的组合

这让 Cause 相比简单的 Result 能够捕获更丰富、更复杂的错误状态。

Exit 与 Effect 的对比

Exit 实际上是 Effect 的子类型。这意味着 Exit 值也可以被视为 Effect 值。

  • 从本质上讲,一个 Exit 就是一次“常量计算”。
  • Effect.succeed 本质上等同于 Exit.succeed
  • Effect.failCause 等同于 Exit.failCause