Search code examples
alamofirerx-swift

RxSwift & alamofire, How to send http request after previous request arrived?


I need to send http request in RxSwift & Alamofire circumstance and send it synchronously which means ...

send(1)...response(1)

-------------------- send(2)...response(2)

-----------------------------------------send(3)...response (3)

and This is my code

            Observable.from(devicesArray)
            .concatMap { (device) in
                return HTTPRequest.deleteDevice(withDevice: device)
            }.subscribe({ (event) in
                log.debug("Remove device successfully")
            }).disposed(by: self.disposeBag)

and deleteDevice is

func deleteDevice(withDevice device:Device) -> Single<String> {

    return Alamofire.request("http://example.com/\(device.deviceId)", method: .delete, parameters: nil, headers: self.headers()).rx
        .responseJSON()
        .retry(self.retryMaxAttempCount)
        .asSingle()
        .observeOn(SerialDispatchQueueScheduler(qos: .default))
        .map({ (response) in
            guard let json = response.value as? [String: Any] else {
                throw HTTPManagerError.invalidResponse
            }

            guard let resultCode = json["resultCode"] as? String else {
                throw HTTPManagerError.invalidResponse
            }

            if resultCode == "0000" || resultCode == "0101" {
                return resultCode
            } else {
                throw HTTPManagerError.invalidResponse
            }
        })
        .observeOn(MainScheduler.instance)
}

Now every single HTTPRequest.deleteDevice function requested in parallel.

So How could I make this request wait until a previous request get finished?

Thanks.


Solution

  • The key here is to make an array of observables and concat them:

    // first we create a deleteDevice observable for each item. 
    // Remember, they don't actually make a network call until subscribed to and concat only subscribes to each once the previous one is done.
    Observable.concat(
        devicesArray.map { deleteDevice(withDevice: $0) }
            .map { $0.asObservable() } // because concat doesn't exist for Singles.
            .map { $0.catchErrorJustReturn("\($0) not deleted.") } // make sure that all deletes will be attempted even if one errors out.
        )
        // the above will emit a string every time a delete finishes.
        // `.toArray()` will gather them together into an array.
        .toArray()
        .subscribe(onNext: { results in
    
        })
        .disposed(by: disposeBag)