fp-ts 如何在pipe中处理异步操作并避免嵌套fold
优化方案
你遇到的嵌套fold问题可以通过 TaskEither 的链式组合能力解决,核心思路是把两个顺序执行、可能失败的异步操作合并为单一的Either流,最终只做一次结果处理。
优化后代码
import * as TE from 'fp-ts/TaskEither' import { pipe } from 'fp-ts/function' public async initialize( @requestParam('site') site: string, @request() req: Request, @response() res: Response ) { const nameAndPublicId = LocationService.retailOnlineLocationName(site); const stationName = StationService.retailOnlineStationName(site); await pipe( // 第一步创建Location,将返回的Promise<Either>转为TaskEither TE.fromTask(() => this.locationService.createLocation( site, nameAndPublicId, nameAndPublicId )), // 前序操作成功后,拿到Location实例执行Station创建 TE.chain((loc: LocationDTO) => TE.fromTask(() => this.stationService.createStation(site, stationName, loc.id) )), // 统一处理最终结果,仅需一次fold TE.fold( (err: ApiError) => () => ConfigController.respondWithError(err, res), (_: StationDTO) => () => res.status(201).send() ) )(); } static respondWithError(err: ApiError, res: Response) { res.status(err.statusCode).json(err); }
原理解释
- 你之前嵌套fold的原因是没有将两个有依赖关系的失败感知操作做链式组合,而是在第一个操作的成功分支里单独处理第二个操作的Either结果。
TaskEither是fp-ts专门用于封装「异步执行、可能返回错误」场景的类型,TE.chain(又称flatMap)会在前一个操作成功时把结果传入后续操作,前序失败时直接透传错误、跳过后续执行。- 最终整个pipe会返回一个聚合了两步操作结果的TaskEither,只需要一次fold就可以统一处理所有错误和最终成功的场景,完全消除嵌套结构。
如果你的service层方法本身就返回TaskEither类型,还可以省去TE.fromTask的转换步骤,代码会更简洁流畅。
内容的提问来源于stack exchange,提问作者mattmar10
相关产品推荐
相关产品推荐

