本资料介绍如何用 fp-ts 的 TaskEither 编写实用的异步代码,核心目标是用清晰的管道替代层层嵌套的 try/catch 与回调地狱,并在出错时保留错误上下文。
一、核心概念 资料把 TaskEither 解释为一个异步操作,用于跟踪成功或失败。例如 TaskEither<Error, User> 表示“一个异步操作,要么以 Error 失败,要么以 User 成功”。不需要复杂术语即可理解。
二、包装 Promise 写作中给出“先包装一次、到处复用”的思路:用 TE.tryCatch 接收两个参数——一个可能抛错的异步函数,以及一个把抛出的值转换为自己错误类型的函数。还介绍了几种构造值的方式:TE.right 包装成功值,TE.left 包装失败值,TE.fromNullable 把 null/undefined 变成错误,TE.fromPredicate 依据条件生成错误。示例中定义了一个可复用的 fetchJson 包装器,并说明 TE.tryCatch 对 HTTP 非 ok 响应抛出错误、再统一转换为 Error。
三、串联异步操作 资料对比了“嵌套 await 与 try/catch”的反例,与使用 pipe + TE.chain 的扁平管道写法。并说明何时用 map、何时用 chain:map 用于同步且不会失败的转换;chain(或 flatMap)用于返回另一个 TaskEither 的异步或可能失败的转换。还介绍用 Do 记法与 TE.bind 累积多个步骤的中间值,避免手工层层穿透参数,最后用 TE.map 组装所需结果对象。文档中的 processOrder 示例包含 order、user、payment、shipment 等字段。
四、顺序与并行 资料区分两种执行方式。顺序执行适用于每一步依赖上一步结果、需要遵守限流、顺序有意义的场景;并行执行适用于操作彼此独立、追求速度、按 ID 批量获取资源的场景。并行实现使用 sequenceT(TE.ApplyPar),并行数组操作使用 TE.traverseArray,并提示它会快速失败(fail fast):任一请求失败则整体失败,首个之后的错误会丢失。对于需要限制并发的情况,资料给出了先按批次切分、批次之间顺序执行、批次内部并行的做法,并给出 chunk 辅助函数。同时特别指出看似并行但存在依赖的错误示例(创建用户与创建资料需使用用户 ID,属于竞态),应改为顺序执行。
五、错误恢复 资料给出多种恢复模式:用 TE.orElse 回退到备用来源(如先 API 后缓存,或多级回退到默认配置);按错误信息或错误标签做条件恢复,部分错误转为降级结果、其他错误继续向上传递;定义带 _tag 的联合类型 ApiError(NotFound、NetworkError、Unauthorized)并在 orElse 中按标签分派不同处理;结合 fp-ts/Task 实现带指数退避的重试函数 retry(示例为最多 3 次、基础延迟 1000ms、延迟翻倍);以及用 TE.getOrElse 结合 T.of 提供默认值并移除错误通道,或用 orElse 转 right 保留错误通道但始终成功。
六、真实 API 与数据库示例 资料给出完整的请求封装:定义 ApiError(code、message、status、details),实现 request 函数统一处理请求头、非 ok 响应体解析、204 No Content,并在 catch 中把异常规范化为 ApiError;随后封装出 api.get/post/put/delete 客户端。数据库部分以 Prisma 为例,定义带 _tag 的 DbError(NotFound、UniqueViolation、ConnectionError),实现 wrapPrisma 把 Prisma 已知请求错误(P2002 唯一约束、P2025 记录不存在)映射为自定义错误,并用仓储模式给出 findById、findByEmail、create、update、delete 等方法。资料最后在 createUserService 处截断,后续内容暂未提供。
七、适用场景与限制 该资料适合使用 TypeScript 与 fp-ts、需要规范化异步错误处理、组合多个异步步骤、控制并发与实现重试/降级的开发场景。限制方面:需要熟悉 fp-ts 的 pipe、TaskEither、Apply 等 API;traverseArray 并行会快速失败并丢失首个之后的错误;并行不适用于存在依赖的操作;示例中的并发批大小、重试次数与延迟均为演示值,不代表通用建议。资料未提供安装步骤、包版本要求、性能数据或收费信息,这些内容暂未提供。