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

如何在fp-ts中结合Either与异步函数使用?

关于fp-ts异步流程优化的解答

首先,你的写法能正确运行,但不算fp-ts里最地道的函数式风格——手动用E.isLeft做分支判断,打破了链式调用的流畅性,而且直接await异步函数没有借助fp-ts的异步容器管理,丢失了函数式编程的组合优势。

要实现单个pipe完成全部逻辑,需要用到TaskEither(通常缩写为TE)——它是Either的异步版本,专门用来封装“可能失败的异步操作”,完美适配你的场景。

优化后的代码示例

import * as E from 'fp-ts/Either'
import * as TE from 'fp-ts/TaskEither'
import { pipe } from 'fp-ts/function'

// 假设 getItem 类型为: (id: Item["id"]) => Promise<Item | null>
const fetchItem = pipe(
  // 1. 从请求体获取itemId,转成Either(处理null/undefined情况)
  body.itemId,
  E.fromNullable('Item ID is missed'),
  
  // 2. 将Either转为TaskEither,进入异步流程上下文
  TE.fromEither,
  
  // 3. 链式调用异步函数,同时处理"获取不到item"的情况
  TE.chain(itemId => 
    TE.chainNullableK(() => getItem(itemId))('cant find item')
  )
)

// 执行TaskEither,得到最终的Either结果
const item: E.Either<string, Item> = await fetchItem()

代码说明

  1. TE.fromEither: 把同步的Either转为异步的TaskEither,让后续能链式调用异步操作。
  2. TE.chainNullableK: 这是fp-ts提供的组合子,专门用来处理“返回值可能为null/undefined的异步函数”——它会自动把null转为指定的错误信息(这里是'cant find item'),省去手动判断null的步骤。

如果你不想用chainNullableK,也可以手动用TE.fromPromise + TE.fromEither组合实现:

const fetchItem = pipe(
  body.itemId,
  E.fromNullable('Item ID is missed'),
  TE.fromEither,
  TE.chain(itemId => 
    pipe(
      getItem(itemId),
      TE.fromPromise, // 把Promise转为TaskEither,捕获异步调用的异常
      TE.chain(item => TE.fromEither(E.fromNullable('cant find item')(item)))
    )
  )
)

这种写法全程用pipe串联逻辑,没有命令式的分支判断,完全符合fp-ts的函数式编程理念,同时还能自动处理异步调用的异常(如果getItem抛出错误,TE.fromPromise会把错误转为Left)。

内容的提问来源于stack exchange,提问作者Petr Tcoi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 11:21:02