代码之家  ›  专栏  ›  技术社区  ›  pankaj

在RxSwift的for循环中调用多个API请求的最佳方法

  •  2
  • pankaj  · 技术社区  · 7 年前

    我必须使用for循环进行几个api调用(大约100个),完成后我需要完成Observable。我使用它如下:

    func getMaterialInfo(materialNo:[String]) -> Observable<[String: Material]>{
        return Observable.create({ (observable) -> Disposable in
            for (index,mat) in materialNo.enumerated(){
                // Pass the material number one by one to get the Material object
                self.getMaterialInfo(materialNo: mat).subscribe(onNext: { material in
                    var materialDict: [String: Material] = [:]
                    materialDict[material.materialNumber] = material
                    observable.onNext(materialDict)
                    if index == (materialNo.count-1){
                        observable.onCompleted()
                    }
                }, onError: { (error) in
                    observable.onError(error)
                }, onCompleted: {
                }).disposed(by: self.disposeBag)
            }
            return Disposables.create()
        })
    }
    

    虽然回路工作正常可观察到的。完成的调用了(),但调用方方法未接收到它。

    private func getImage(materialNo:[String]){
        if materialNo.isEmpty {
            return
        }
        var dictMaterials = [String:String]()
        materialService.getMaterialInfo(materialNo: materialNo).subscribe(onNext: { (materials) in
            for (key,value) in materials{
                if (value.imageUrl != nil){
                    dictMaterials[key] = value.imageUrl
                }
            }
        }, onError: { (error) in
    
        }, onCompleted: {
            self.view?.updateToolImage(toolImageList: dictMaterials)
        }, onDisposed: {}).disposed(by: disposeBag)
    }
    

    1 回复  |  直到 7 年前
        1
  •  1
  •   CloakedEddy    6 年前

    编辑(3月5日)

    我重温了这个答案,因为我不确定当我写下面的代码示例时,我的大脑在做什么。我会做这样的事情:

    func getMaterialInfo(materialNo: String) -> Observable<[String: Material]> {
        // ...
    }
    
    func getMaterialInfo(materialNumbers:[String]) -> Observable<[String: Material]>{
            let allObservables = materialNumbers
                .map { getMaterialInfo(materialNo: $0) }
    
            return Observable.merge(allObservables)
    }
    

    原始答案

    从你的代码中,我解释说 getMaterialInfo 同时进行调用。基于此,我会重写你的 getMaterialInfo(:[_]) 方法来使用 .merge 操作员。

    func getMaterialInfo(materialNo:[String]) -> Observable<[String: Material]>{
        return Observable.create({ (observable) -> Disposable in
            // a collection of observables that we haven't yet subscribed to
            let allObservables = materialNo
                .map { getMaterialInfo(materialNo: $0) }
    
            return Observable.merge(allObservables)
        }
        return Disposables.create()
    }
    

    注意使用 merge 同时订阅所有可观察到的,同时触发100个网络请求。对于顺序订阅,请使用 concat 取而代之的是!

    推荐文章