fp-ts如何处理多个Right类型不同的Promise<Either>场景
解决方案
你需要的是同Left类型、不同Right类型的Either聚合能力,这类场景有标准的工具函数可以直接调用,完全不需要手动嵌套fold。
基于fp-ts的实现(TS生态最常用的Either实现)
写法1:使用E.all(最简推荐)
fp-ts 2.11+内置的all函数专门处理该场景,支持元组类型自动推导,仅需2行代码即可替换所有嵌套逻辑:
// 合并三个Either,返回 Either<ApiError, [LocationDTO, StationDTO, CustomerDTO]> const combinedE = E.all([locationE, stationE, customerE]) // 映射为你需要的对象结构 const stationAndLocationAndCustomer = E.map( ([location, station, customer]) => ({ location, station, customer }) )(combinedE)
语义非常明确:所有输入Either都为Right时才执行map逻辑,任意一个为Left则直接返回该Left。
写法2:Do notation(适合复杂场景)
如果后续需要扩展更多前置校验、或者字段数量较多时,用Do notation可读性更高,可直接生成目标结构:
const stationAndLocationAndCustomer = E.pipe( E.Do, E.bind('location', () => locationE), E.bind('station', () => stationE), E.bind('customer', () => customerE) )
该写法无需额外的map操作,直接返回Either<ApiError, {location: LocationDTO, station: StationDTO, customer: CustomerDTO}>类型,每个字段的来源一目了然。
额外优化:异步层直接合并
你可以把聚合逻辑提前到异步阶段,省略手动await Promise.all拆包的步骤:
import * as TE from 'fp-ts/TaskEither' import { pipe } from 'fp-ts/function' const stationAndLocationAndCustomer = await pipe( TE.all([ this.locationService.getRetailOnlineLocation(siteOrigin), this.stationService.getRetailOnlineStation(siteOrigin), this.customerService.createCustomer(siteOrigin, createCustReq) ]), TE.map(([location, station, customer]) => ({ location, station, customer })) )()
自定义Either的实现思路
如果你是自己实现的Either类型,可以参考以下逻辑实现通用的all工具函数:
- 遍历输入的Either元组/数组
- 遇到第一个Left就直接返回该Left
- 所有输入都为Right时,收集所有Right值,返回包裹了值数组/元组的Right
内容的提问来源于stack exchange,提问作者mattmar10
相关产品推荐
相关产品推荐

