Effect v3 到 v4 如何把 Effect.fork 与 Effect.forkDaemon 迁移到 forkChild 与 forkDetach
2026/9/15 11:50:21 网站建设 项目流程

Effect v3 到 v4 如何把 Effect.fork 与 Effect.forkDaemon 迁移到 forkChild 与 forkDetach

【免费下载链接】effectBuild production-ready applications in TypeScript项目地址: https://gitcode.com/GitHub_Trending/ef/effect

Effect 仓库在 v4 中重命名了fork*系列组合子,并且所有 fork 变体都改为接受一个选项对象来控制 fiber 启动行为。如果你的 v3 代码里还有Effect.forkEffect.forkDaemon调用,升级到 v4(仓库中packages/effect/package.json当前版本为4.0.0-rc.115)后这些旧名已经不存在,对应调用点必须改为Effect.forkChildEffect.forkDetach。仓库中 migration/forking.md 是这次重命名的专门说明,migration/v3-to-v4.md 与 migration/annotations/effect__Effect.yaml 里有逐条 API 映射,本文按这两份文档把迁移路径走一遍。

先查重命名对照表,确定每个调用点改成什么

migration/forking.md 给出的完整映射如下:

v3v4说明
Effect.forkEffect.forkChildFork as a child of the current fiber
Effect.forkDaemonEffect.forkDetachFork detached from parent lifecycle
Effect.forkScopedEffect.forkScoped名称不变,仍绑定当前Scope
Effect.forkInEffect.forkIn名称不变,仍 fork 到指定Scope
Effect.forkAll已移除
Effect.forkWithErrorHandler已移除

迁移时的基本动作就是全局搜索Effect.fork(Effect.forkDaemon(,按上表替换;forkScopedforkIn不需要改名,但签名上同样新增了可选的 options 对象,见下文。

迁移 Effect.fork 到 Effect.forkChild

v3 写法(文档示例):

import { Effect } from "effect" const fiber = Effect.fork(myEffect)

对应的 v4 写法:

import { Effect } from "effect" const fiber = Effect.forkChild(myEffect)

Effect.forkChild在 v4 源码中标注为@since 4.0.0,返回Effect<Fiber<A, E>, never, R>,即 fork 动作本身是一个 Effect,fiber 结果通过它拿到。仓库源码里的官方示例(见 packages/effect/src/Effect.ts 中forkChild的 JSDoc)展示了完整的验证方式:

import { Effect, Fiber } from "effect" const task = Effect.succeed("result") const program = Effect.gen(function*() { const fiber = yield* task.pipe(Effect.forkChild) const result = yield* Fiber.join(fiber) return result }) await Effect.runPromise(program) // => "result"

把 fork 后的 fiber 用Fiber.join接回来,运行结果为"result",说明子 fiber 的返回值与原Effect.fork的语义一致。

迁移 Effect.forkDaemon 到 Effect.forkDetach

v3 写法(文档示例):

import { Effect } from "effect" const fiber = Effect.forkDaemon(myEffect)

对应的 v4 写法:

import { Effect } from "effect" const fiber = Effect.forkDetach(myEffect)

migration/annotations/effect__Effect.yaml 中Effect.forkDaemon的迁移备注是:forkDaemon 语义不变,只是改名为从父 fiber 生命周期中脱离的Effect.forkDetach。同样地,源码 JSDoc 示例给出了 detach 场景的验证路径:

import { Effect, Fiber } from "effect" const daemonTask = Effect.succeed("daemon result") const program = Effect.gen(function*() { const fiber = yield* daemonTask.pipe(Effect.forkDetach) return yield* Fiber.join(fiber) }) await Effect.runPromise(program) // => "daemon result"

运行输出"daemon result",说明 detached fiber 的结果仍然可以通过Fiber.join观察。

使用 v4 新增的 fork 选项对象

v4 中forkChildforkDetachforkScopedforkIn都接受同一个可选选项对象(见 migration/forking.md 与 packages/effect/src/Effect.ts 中的签名):

{ readonly startImmediately?: boolean | undefined readonly uninterruptible?: boolean | "inherit" | undefined }
  • startImmediately— 为true时,fork 出的 fiber 立即开始执行而不是延迟执行;默认undefined(延迟)。
  • uninterruptible— 控制 fork 出的 fiber 是否可被中断:true设为不可中断,"inherit"继承父 fiber 的中断性,undefined使用默认行为。

两种调用形态在文档中都给出了示例。data-last(curried,在pipe中传选项):

import { Effect } from "effect" const fiber = myEffect.pipe( Effect.forkChild({ startImmediately: true }) )

data-first(effect 和选项同时传入):

import { Effect } from "effect" const fiber = Effect.forkChild(myEffect, { startImmediately: true })

注意这个选项对象是 v4 新增的,v3 时代没有对应参数;如果 v3 代码里 fork 后靠“立即开始执行”的隐式行为做时序假设,迁移时要显式评估是否需要startImmediately: true,不要默认两者行为相同。

处理被移除的 forkAll 与 forkWithErrorHandler

如果你搜索时还命中了这两个已移除的组合子,migration/forking.md 与 migration/v3-to-v4.md 给出的替代方式一致:

  • Effect.forkAll:改用Effect.forEach + Effect.forkChild逐个显式 fork,或使用更高层的并发组合子。
  • Effect.forkWithErrorHandler:改为Effect.forkChild + Fiber.await,即显式 fork 后通过观察 fiber 的结果来处理错误(文档也给出了Fiber.join作为观察 fiber 结果的方式)。

这两项不在“改名”范围内,是真正被删掉的 API,没有直接同签名的替代品。

验证迁移结果

仓库文档给出的可执行验证方式有两层:

  1. 编译检查:v4 源码中旧名已不存在。可以确认 packages/effect/src/Effect.ts 中没有forkforkDaemonforkAllforkWithErrorHandler的导出(实际存在的只有forkChildforkDetach及未改名的forkScopedforkIn)。因此迁移完成后,只要项目里所有Effect.fork(...)/Effect.forkDaemon(...)引用都能通过类型检查,就说明没有遗漏的调用点。
  2. 运行检查:按上文两个 JSDoc 示例各跑一遍,forkChild示例应输出"result"forkDetach示例应输出"daemon result"(文档示例输出)。仓库内测试代码 ai-docs/src/09_testing/10_effect-tests.ts 中也有Effect.forkChild配合TestClock的实际用法可参考:
const fiber = yield* Effect.forkChild( Effect.sleep(60_000).pipe(Effect.as("done" as const)) ) // Move virtual time forward to complete sleeping fibers immediately. yield* TestClock.adjust(60_000)

限制与边界

  • 本文覆盖的是 fork 组合子的重命名迁移;forkScopedforkIn名称不变,但同样接受新的 options 对象,如果 v3 代码依赖其旧参数形态需要按 v4 签名调整。
  • v4 当前处于 RC 阶段(4.0.0-rc.115),fork 家族 API 在正式版前仍有变动可能,升级时建议锁版本并复核 migration/v3-to-v4.md 中Effect.fork*相关条目是否有更新。
  • 若代码中通过Micro.forkDaemon等入口调用,v4 中 Micro 已移除,统一改用Effect.forkDetach(见 migration/v3-to-v4.md 中Micro.forkDaemon条目)。

【免费下载链接】effectBuild production-ready applications in TypeScript项目地址: https://gitcode.com/GitHub_Trending/ef/effect

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询