3

我目前有以下代码

func updateItems(_ observable: Observable<ContainingEntity>) -> Observable<ContainingEntity>{
    return observable
        .concatMap({ (containingEntity) -> Observable<ContainingEntity> in
            guard let itemEntity = orderEntity.itemEntity,
                itemEntity.name.count == 0 else{
                    return Observable.just(entity)
            }

            print("Need to fetch name of item #\(itemEntity.id)")

            return RestManager.getDetailOf(item: itemEntity)
                .flatMap({ (updatedItemEntity) -> Observable<ContainingEntity> in
                    var updatedContainingEntity = containingEntity
                    containingEntity.itemEntity = updatedItemEntity
                    print("Fetched item name: \(itemEntity.name)")
                    return Observable.just(containingEntity)
                })
        })
}

基本上,我需要确保每个ContainingEntity的itemEntity都有一个名称,如果没有,请向 Moya 请求它。

但我正面临来自这两种打印的以下类型的输出:

  • 需要获取项目 #1 的名称
  • 需要获取项目 #2 的名称
  • 需要获取项目 #3 的名称
  • 获取的项目名称:Name1
  • 获取的项目名称:Name2
  • 获取的项目名称:Name3

这意味着我的 concatMap 中的操作是并行执行的,这是我不想要的,因为请求冗余和一些我没有在这里显示的缓存系统:我可以有 30 次相同的项目 ID,我不想请求它30 次。

我期待的是:

  • 需要获取项目 #1 的名称
  • 获取的项目名称:Name1
  • 需要获取项目 #2 的名称

  • 获取的项目名称:Name2

  • 需要获取项目 #3 的名称
  • 获取的项目名称:Name3

我该如何解决这个问题?非常感谢您的帮助。

更新:

我现在使用某种简单的缓冲区,它保存需要更新的ItemEntities并将这些项目分配给具有相同项目标识符的下一个ContainingEntities 。这可以防止 Moya 多次执行相同的请求。

它工作得很好,但我不太喜欢RX外部的这种机制的想法......

4

1 回答 1

1

我认为使用VariableorBehaviorSubject来控制顺序加载可以工作(下面的代码)。

但是,您可能需要重新考虑加载架构,因为通过使用此代码,您的加载时间可能不是最佳的。

限制同时进行的并行请求的数量可能属于其他组件,例如您的网络层。

我没有测试下面的代码,所以它甚至可能无法编译 - 如果它有效,请告诉我并接受答案。

func updateItems(_ observable: Observable<ContainingEntity>) -> Observable<ContainingEntity>{
  let trigger = BehaviorSubject<Int>(value: 0)
  let sequential = Observable.zip(observable, trigger) { return $0.0 }
  return sequential
    .concatMap({ (containingEntity) -> Observable<ContainingEntity> in
      guard let itemEntity = orderEntity.itemEntity,
        itemEntity.name.count == 0 else{
          return Observable.just(entity)
      }

      print("Need to fetch name of item #\(itemEntity.id)")

      return RestManager.getDetailOf(item: itemEntity)
        .flatMap({ (updatedItemEntity) -> Observable<ContainingEntity> in
          var updatedContainingEntity = containingEntity
          containingEntity.itemEntity = updatedItemEntity
          print("Fetched item name: \(itemEntity.name)")
          trigger.onNext(0)
          return Observable.just(containingEntity)
        })
    })
}
于 2018-04-25T00:14:01.843 回答