fp-ts中如何实现管道流程分支并行执行后合并结果
实现方案
你可以通过fp-ts提供的Do notation(bind语法)或者并行组合子实现分支后合并的逻辑,以下是两种常用写法:
方案1:Do/bind写法(可读性最佳,适合多中间结果复用场景)
这种写法可以把每一步的计算结果存入上下文,后续任意步骤都可以读取之前的任意结果,完全符合你的需求:
import { pipe } from 'fp-ts/function' import * as E from 'fp-ts/Either' // 你的原方法 const getProduct = () => E.right({ count: 10, pricePerItem: 5 }) // 步骤2:基于原始产品数据加tax字段 const addTax = (baseProduct) => E.right({ ...baseProduct, tax: 0.1 }) // 步骤3:基于原始产品数据加delivery字段 const addDelivery = (baseProduct) => E.right({ ...baseProduct, delivery: 0.15 }) pipe( E.Do, // 初始化上下文容器 E.bind('base', () => getProduct()), // 执行步骤1,结果存入上下文的base字段 E.bind('withTax', ({ base }) => addTax(base)), // 用步骤1的结果计算tax,存入withTax字段 E.bind('withDelivery', ({ base }) => addDelivery(base)), // 用步骤1的结果计算delivery,存入withDelivery字段 E.map(({ withTax, withDelivery }) => ({ ...withTax, ...withDelivery })), // 合并两个结果 E.fold( (e) => console.log(`error: ${e}`), (it) => console.log(`ok ${it.count} ${it.pricePerItem} ${it.tax} ${it.delivery}`) ) )
任意步骤返回Left时,流程会直接进入错误分支,和你原有串行逻辑的错误处理规则一致。
方案2:sequenceT并行组合(适合独立任务合并场景)
如果步骤2、3完全独立,不需要复用更多中间结果,可以用更简洁的并行组合子实现:
import { pipe } from 'fp-ts/function' import * as E from 'fp-ts/Either' import { sequenceT } from 'fp-ts/Apply' const getProduct = () => E.right({ count: 10, pricePerItem: 5 }) const addTax = (baseProduct) => E.right({ ...baseProduct, tax: 0.1 }) const addDelivery = (baseProduct) => E.right({ ...baseProduct, delivery: 0.15 }) pipe( getProduct(), E.chain(base => sequenceT(E.Apply)(addTax(base), addDelivery(base))), // 并行执行两个计算,都成功才返回结果数组 E.map(([withTax, withDelivery]) => ({ ...withTax, ...withDelivery })), // 合并结果 E.fold( (e) => console.log(`error: ${e}`), (it) => console.log(`ok ${it.count} ${it.pricePerItem} ${it.tax} ${it.delivery}`) ) )
两种方案都实现了「步骤2、3均以步骤1输出为输入,之后合并结果」的逻辑,避免了原串行pipe的依赖传递问题。
内容的提问来源于stack exchange,提问作者Kevin Le - Khnle
相关产品推荐
相关产品推荐

