2017-04-20 15 views
1

背景RxSwift - 斯普利特順序分成較小的序列Concat的上

我想實現通過下載使用Range頭塊的文件。

目標

我想利用http請求的一個大的序列插入,我可以然後向的concat一次處理4個請求四個序列。

當前人大常委會

我目前考慮我的程序和使用concat保證之前,我開始了第二次觀察到的第一個請求完成。這樣做的目的是爲了確保我不會因爲請求過多而超負荷阿拉莫菲爾,從而最終導致請求超時。

理想情況下,我想將我的序列分成四個相當的序列,因爲Alamofire設置爲一次處理與主機的四個連接。我想這樣做,因爲我相信這會增加我的下載速度。

下載文件使用大塊

Observable.generate(initialState: 0, condition: { $0 < fileSize }, iterate: {$0 + self.defaultChunkSize}) 
    .map({ (startChunk) in 
     let endChunk = startChunk + self.defaultChunkSize > fileSize ? fileSize : startChunk + self.defaultChunkSize 

     return (startChunk, endChunk) 
    }) 
    .map({ (startChunk: Int, endChunk: Int) -> Observable<FileChunkResult> in 
     self.filesClient.downloadChunkOf(fileId: file.id, startChunk: Int64(startChunk), endChunk: Int64(endChunk)) 
    }) 

    .concat() // <----- This is where I am forcing the large sequence to do one observable at a time 

    .flatMap({ (result: FileChunkResult) -> Observable<FileSaveChunkResult> in 
     switch (result) { 
     case FileChunkResult.success(let chunkData): 
      return self.saveChunkToFile(fileChunk: chunkData, location: urlToSaveTo) 
     case FileChunkResult.failure: // Maybe change this to just default and return Observable.just(FileSaveChunkResult.failure) 
      break 
     case FileChunkResult.parserError: 
      break 
     } 

     return Observable.just(FileSaveChunkResult.failure) 
    }) 
    .flatMap({ (result: FileSaveChunkResult) -> Observable<Progress> in 
     switch (result) { 
     case FileSaveChunkResult.success(let bytesSaved): 
      progress.completedUnitCount += bytesSaved 
     case FileSaveChunkResult.failure: 
      break 
     } 

     return Observable.just(progress) 
    }) 
+0

只是一個供參考。 (1)AlamoFire沒有任何限制你一次四個請求,雖然可能有一些關於你的服務器導致這樣的限制。 (2)以最大1/4的速度並行上傳的四個請求不太可能每個完成速度比按順序上傳四個請求更快。 –

回答

1

下面的代碼將打碎大塊入使用的concat四個相等大小的數組,以確保只有一個保存從每個陣列是活動的時間。這意味着無論某個特定的呼叫有多快或多快,您都將始終保持4 saveChunkToFile的呼叫。

換句話說,它立即啓動四個請求,然後每當前一個請求完成時啓動一個請求。

let generator = Observable.generate(initialState: 0, condition: { $0 < fileSize }, iterate: { $0 + defaultChunkSize }) 
let chunks = generator.map({ (startChunk) -> (Int64, Int64) in 
    let endChunk = (startChunk + defaultChunkSize > fileSize ? fileSize : startChunk + defaultChunkSize) 
    return (startChunk, endChunk) 
}) 

let count = ceil(Double(fileSize)/Double(defaultChunkSize)/4) 
let requests = chunks.window(timeSpan: 0.0, count: Int(count), scheduler: MainScheduler.instance) 
    .flatMap { $0 
     .map({ (startChunk: Int64, endChunk: Int64) -> Observable<FileChunk> in 
      return makeChunkRequest(url: downloadUrl, startChunk: startChunk, endChunk: endChunk) 
     }).concat() 
} 

let downloadObservable = requests 
    .flatMap({ (fileChunk: FileChunk) -> Observable<FileSaveChunkResult> in 
     return saveChunkToFile(fileChunk: fileChunk, location: localDestinationUrl) 
    }).flatMap({ (saveResult: FileSaveChunkResult) -> Observable<Progress> in 
     if case .success(let bytesSaved) = saveResult { 
      progress.completedUnitCount += bytesSaved 
     } 
     return Observable.just(progress) 
    }) 

_ = downloadObservable.subscribe(onNext: { print(Date(), $0) })