FP-TS中使用TaskEither处理多重依赖分支流程的惯用方案是什么?
fp-ts 惯用实现方案
你描述的场景属于fp中非常常见的异步依赖上下文保留场景,fp-ts提供了原生支持的写法,不需要手动处理错误,也不需要修改原有函数的职责:
方案1:基础组合子实现(适合简单依赖)
import { pipe } from 'fp-ts/function' import * as TE from 'fp-ts/TaskEither' const result = pipe( fetchDataA(), // 用chain而非map避免嵌套TaskEither,打包A和B的结果为元组传递到下游 TE.chain((a) => pipe( fetchBBasedOnOutputOfA(a), TE.map((b) => [a, b] as const ) ), TE.chain(([a, b]) => fetchCBasedOnOutputOfAandB(a, b)) )
注:你之前示例里用
TE.map(fetchBBasedOnOutputOfA)实际返回的是TaskEither<Error, TaskEither<Error, TypeB>>的嵌套结构,需要用chain替代map打平层级才是正确写法。
方案2:Do 语法实现(适合复杂依赖图,更推荐
fp-ts提供的Do notation专门用来解决多步依赖、需要保留上游上下文的场景,写法更简洁,无需手动维护元组顺序,嵌套层级更低:
import { pipe } from 'fp-ts/function' import * as TE from 'fp-ts/TaskEither' const result = pipe( TE.Do, // 把fetchDataA的结果绑定到上下文的a字段 TE.bind('a', fetchDataA), // 上下文中的a已经可用,调用fetchB把结果绑定到b字段 TE.bind('b', ({ a }) => fetchBBasedOnOutputOfA(a)), // 上下文同时存在a和b,直接调用fetchC TE.chain(({ a, b }) => fetchCBasedOnOutputOfAandB(a, b)) )
如果后续还要新增依赖步骤,比如需要用a、b、c请求d,只需要继续追加TE.bind即可,非常适合复杂依赖链的场景,全程TaskEither会自动完成错误传递,完全不需要手动判断isRight处理错误分支,也不需要修改原有函数的返回结构,符合单一职责原则。
内容的提问来源于stack exchange,提问作者Richard Howell-Peak
相关产品推荐
相关产品推荐

