You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 05:45:03