如何聚合多个异步Single调用的结果并在fold函数中使用
问题根因
你现有代码的核心问题是:Kotlin标准库的fold是同步聚合操作,你传入的初始值是Boolean类型,但异步请求tasksUseCase.sendOrderStatusForWorker返回的是Single<Boolean>,二者类型完全不匹配,自然无法正常运行。
解决方案
我们只需要把聚合的容器从同步的Boolean改成异步的Single<Boolean>即可,让每一步请求都基于上一步的聚合结果串行执行,最后直接返回聚合好的Single对象:
private fun sendOrderStatus(list: List<OrderStatusEntity>) : Single<Boolean> { // 初始聚合值为Single<Boolean>类型的true return list.fold(Single.just(true)) { accSingle, item -> accSingle.flatMap { previousResult -> // 拿到上一步的聚合结果 if (!item.isTerminal()) { val info = OrderStateParameters( lon = item.orderStatusLon!!, lat = item.orderStatusLat!!, datetime = item.orderStatusDate!! ) val state = OrderState(item.orderId, item.toSend(), info) // 执行当前请求,和之前的结果做与操作聚合 tasksUseCase.sendOrderStatusForWorker(state) .doOnSuccess { markSent(item) } .map { currentResult -> previousResult && currentResult.isSuccess } } else { // 终端状态直接透传之前的聚合结果 Single.just(previousResult) } } } }
补充说明
- 如果你的业务允许并行发送所有请求,可以先把所有非终端状态的请求转换成Single对象,再用
Single.zip统一聚合结果,性能会更高 - 上述实现是串行执行请求,如果某一步请求出现错误,整个流会直接终止并抛出异常,如果需要即使某个请求失败也要继续执行后面的请求,可以给每个请求加
onErrorReturnItem(false)的降级处理
内容的提问来源于stack exchange,提问作者Sagamor Nord
相关产品推荐
相关产品推荐

