503 words
3 minutes
Effect 类型安全错误处理:3. flatMap:组合 Effect

Effect 是程序的完整描述。我们可以将 Effect 相互组合,构建描述更复杂程序的其他 Effect

在这个例子中,我们有 2 个 Effect:fetchRequestjsonResponse

  • fetchRequest 返回一个包含 Response 的 Effect
  • 我们想要从第一个 Effect 中提取 Response 并将其提供给 jsonResponse

问题是我们将 Response 包装在 Effect 内部(Effect<Response>)。我们不能再直接”提取” Response 了:

const fetchRequest = Effect.promise(() =>
  fetch("https://pokeapi.co/api/v2/pokemon/garchomp/")
);

const response: Response = /// 无法直接访问 `Response` 😬

Effect 是计算。它们不持有 Response

无法从 Effect 中获取 Response,因为 Response (还)不存在。

执行 Effect 将产生一个 Response

相反,Effect 提供了函数来描述基于前一个(或多个)Effect 的值要执行的下一步操作。

flatMap:获取值并返回 Effect#

Effect.flatMap 允许访问 Effect 的结果并链接另一个 Effect

  • 第一个参数:我们想要从中提取值的 Effect
  • 第二个参数:提供对第一个 Effect 参数访问权限并返回另一个 Effect 的函数
const fetchRequest = Effect.promise(() =>
  fetch("https://pokeapi.co/api/v2/pokemon/garchomp/")
);

const main = Effect.flatMap(
  fetchRequest, // 👈 从 `fetchRequest` 中提取值
  (response) => // 👈 访问 `Response` 并返回另一个 `Effect`
);

使用 Effect.flatMap,我们可以链接 jsonResponse,因为我们可以访问 response

/// 👇 `Effect<Response>`
const fetchRequest = Effect.promise(() =>
  fetch("https://pokeapi.co/api/v2/pokemon/garchomp/")
);

/// 👇 `Effect<unknown>`(`jsonResponse` 的返回类型)
const main = Effect.flatMap(
  fetchRequest,
  (response) => jsonResponse(response)
);

这可能看起来很奇怪。不再是一行接一行的线性命令式代码,而是使用以其他函数作为输入并返回函数的函数 🙌

现在请耐心等待,Effect 提供了一些编写更好看代码的方法,我们稍后会介绍。

然后我们可以使用 runPromise 运行最终程序:

runPromiserunSync 的等价物,但用于异步程序

const fetchRequest = Effect.promise(() =>
  fetch("https://pokeapi.co/api/v2/pokemon/garchomp/")
);

const jsonResponse = (response: Response) =>
  Effect.promise(() => response.json());

const main = Effect.flatMap(
  fetchRequest,
  (response) => jsonResponse(response)
);

Effect.runPromise(main);

我们甚至可以将代码简化为:

const fetchRequest = Effect.promise(() =>
  fetch("https://pokeapi.co/api/v2/pokemon/garchomp/")
);

const jsonResponse = (response: Response) =>
  Effect.promise(() => response.json());

const main = Effect.flatMap(
  fetchRequest,
  jsonResponse
);

Effect.runPromise(main);

Effect Playground

Effect 类型安全错误处理:3. flatMap:组合 Effect
https://0bipinnata0.my/posts/course/effect-beginners-complete-getting-started/type-safe-error-handling-with-effect/flatmap-composing-effects/
Author
0bipinnata0
Published at
2025-08-30 13:16:43