如何在ZIO中并行执行两个操作并获取各自结果(非快速失败)
ZIO并行改造:非快速失败的并行执行方案
原代码通过顺序for推导式处理基站和WiFi的API调用,一旦某步骤失败就会快速终止整个流程。要实现并行执行且各自保留成功/失败结果的需求,可借助ZIO的错误捕获与并行组合操作符实现:
改造步骤
- 封装独立任务并捕获错误:将基站和WiFi的处理流程分别封装为独立ZIO任务,通过
either把错误通道的异常转换为值通道的Either类型,确保单个任务不会因错误终止,而是返回包含成功/失败信息的结果。 - 并行执行任务:使用ZIO的
zipPar或parMapN并行执行两个任务,等待两者都完成后获取各自的结果。 - 处理合并结果:在
mapResult中接收两个Either结果,根据业务逻辑处理各种成功/失败组合(双成功、单成功单失败、双失败)。
改造后代码示例
// 封装基站处理任务:捕获所有错误,返回Either类型 val cellTowerTask: ZIO[Any, Nothing, Either[RequirementsFailure, GoogleMapsResult]] = CellHintTransformer.createGoogleApiPayload(cellAndWifiHints.cellHints) .mapError(mapRequirementsFailure) .flatMap(googleMapsApi.call) .either // 封装WiFi处理任务:逻辑同基站任务 val wifiHintTask: ZIO[Any, Nothing, Either[RequirementsFailure, GoogleMapsResult]] = WlanHintTransformer.createGoogleApiPayload(cellAndWifiHints.wifiHints) .mapError(mapRequirementsFailure) .flatMap(googleMapsApi.call) .either // 并行执行两个任务,处理合并结果 for { (cellResult, wifiResult) <- cellTowerTask.zipPar(wifiHintTask) finalResult <- mapResult(cellResult, wifiResult) } yield finalResult
关键说明
either操作符:将ZIO[R, E, A]转换为ZIO[R, Nothing, Either[E, A]],把错误从错误通道移到值通道,确保任务自身不会失败,而是携带错误信息继续执行。zipPar并行组合:与顺序的zip不同,zipPar会同时启动两个任务,等待两者都完成后返回结果元组,不会因其中一个任务的错误(已被捕获为Either)而终止另一个任务。mapResult适配:需要调整mapResult的参数类型,接收两个Either[RequirementsFailure, GoogleMapsResult],并根据业务需求处理不同的结果组合(例如优先使用基站结果、合并有效结果或返回错误汇总)。
简化写法
如果不需要中间变量,也可以用parMapN直接组合任务并传入处理函数:
ZIO.parMapN(cellTowerTask, wifiHintTask)(mapResult)
内容的提问来源于stack exchange,提问作者Chris W.
相关产品推荐
相关产品推荐

