使用Dartz调用多个Future时如何避免嵌套fold写法
优化方案
dartz的Either本身是右偏向Monad,支持通过链式调用扁平化嵌套逻辑,避免多层fold嵌套,有两种常用实现方式:
方案1:直接使用bind拼接异步结果
适合不想引入额外类型的场景,利用Future的then结合Either的bind方法拼接逻辑,全程仅需1次fold:
final Either<Failure, Unit> result = await deleteA() .then((resA) => resA.bind((_) async => await deleteB())); result.fold( (failure) => handleFailure(), (success) => handleSuccess(), );
逻辑说明:
- 如果
deleteA返回Left,bind会直接跳过后续逻辑保留Left值,不会调用deleteB - 只有
deleteA返回Right时才会执行deleteB,deleteB返回的Left/Right会直接作为最终结果 - 最终结果的fold分支和你原有嵌套写法的逻辑完全等价
方案2:使用TaskEither封装异步操作(更推荐)
TaskEither是dartz专门为异步Either操作设计的类型,链式调用更顺滑,后续新增步骤也不需要改动结构:
// 把原有异步方法封装为TaskEither final deleteATask = TaskEither(deleteA); final deleteBTask = TaskEither(deleteB); // 链式拼接操作,任意一步失败都会直接短路 final Either<Failure, Unit> result = await deleteATask .flatMap((_) => deleteBTask) .run(); result.fold( (failure) => handleFailure(), (success) => handleSuccess(), );
如果后续需要新增更多串行、前序成功才执行的步骤,直接在链上追加flatMap即可,无任何嵌套:
final result = await deleteATask .flatMap((_) => deleteBTask) .flatMap((_) => deleteCTask) // 新增第三步,无需嵌套 .flatMap((_) => deleteDTask) // 新增第四步 .run();
核心原理
dartz的Either和TaskEither都是右偏向结构,所有转换操作仅作用于成功的Right值,任意一步出现Left(失败)都会直接跳过后续所有操作,保留第一个出现的错误值,完全符合你“前序成功才执行后续”的需求。
内容的提问来源于stack exchange,提问作者Manu
相关产品推荐
相关产品推荐

