使用RxAlamofire限制同时下载

时间:2016-11-10 02:17:26

标签: alamofire rx-swift rxalamofire

鉴于我的应用程序将从服务器下载文件而我只希望 1下载同时进行,那么如何使用RxAlamofire完成此操作?我可能只是错过了一个Rx运算符。 这是粗略的代码:

Observable
    .from(paths)
    .flatMapWithIndex({ (ip, idx) -> Observable<(Int, Video)> in
        let v = self.files![ip.row] as! Video
        return Observable.from([(idx, v)])
    })
    .flatMap { (item) -> Observable<Video> in
        let req = URLRequest(url: item.1.downloadURL())

        return Api.alamofireManager()
            .rx
            .download(req, to: { (url, response) -> (destinationURL: URL, options: DownloadRequest.DownloadOptions) in
              ...
            })
            .flatMap({ $0.rx.progress() })
            .flatMap { (progress) -> Observable<Float> in
              // Update a progress bar
              ...
            }
            // Only propagate finished items
            .filter { $0 >= 1.0 } 
            // Return the item itself
            .flatMap { _ in Observable.from([item.1]) }
    }
    .subscribe(
      onNext: { (res) in
        ...
      },
      onError: { (error) in
        ...
      },
      onCompleted: {
        ...
      }
    )

我的问题是 a) RxAlamofire会同时下载多个项目, b)(进度)块会多次调用这些不同的项目(不同的每个进展信息,导致用户界面表现得有点奇怪)。

如何确保逐个下载而不是同时进行下载?

1 个答案:

答案 0 :(得分:0)

alamofireManager().rx.download()是同时还是连续下载?

我不确定它是怎么做的,所以先测试一下。隔离此代码并查看它是否一次执行多个下载。如果是,请阅读有关串行下载而不是并发下载的文档。

如果一次下载一个,则表示它与您的Rx代码有关,触发了进度条更新问题。如果它不能一次下载一个,那么这意味着我们只需要阅读Alamofire的文档,了解如何一次下载一个。

复杂的转化和副作用

需要考虑的是,您的数据流变得越来越复杂,难以调试,因为在一个流中发生了很多事情。由于多个平面地图,可能会有更多的排放影响进度条更新。获取Observable的众多平面地图操作也可能是进度条上多次触发更新的原因。

复杂数据流

在一个数据流中,您(a)执行网络呼叫(b)更新进度条(c)过滤完成的视频(d)并在开始时使用flatMapWithIndex返回到您想要的视频以将ID和视频模型,以便您可以在最后返回模型。有点复杂......我的猜测是,通过调用$0.rx.progress()创建一个热观察,可能会导致奇怪的进度条更新。

我制作了一个github gist我的Rx Playground,试图模拟你想要做的事情。

在功能性反应式编程中,如果首先定义数据流/可观察量,它将更易读,更容易调试。在我的要点中,我从观察者开始,以及我计划如何建模下载进度。

如果RxAlamofire查询一次下载1个,并且它正确显示UIProgressBar的进度值,此代码将避免并发问题。

旁注

您是否需要跟踪每个下载项目的个人进度下载量?或者您希望您的进度条只是按完成的下载项递增?

另外,要注意滥用多个flatMaps as explained here链的可能危险。