Chaining Multiple Network Request with Alamofire and RxSwift

Almost every iOS app making a network request. One of the most frustrating to deal with network request is when you need to do multiple calls of which the result of request #1 determine the query or path of request #2 and so on. It’s hard to do it and keep track of the requests, especially when you need to look back at the code after not touching it for some time.

When you need to do multiple calls with Alamofire, most developers were doing it like this :

func request1() {
    Alamofire.request(requestURL1).responseJSON { [unowned self] (response) in
        if let data = response.result.value {
            let json = JSON(data)
            self.request2(value: json["key"].stringValue)
        }
    }
}

func request2(value: String) {
    Alamofire.request("\(requestURL2)?query=\(value)").responseJSON { [unowned self] (response) in
        if let data = response.result.value {
            let json = JSON(data)
            self.doSomething(json["key"].arrayValue)
        }
    }
}

*To convert Any to a useful JSON data structure, I’m using SwiftyJSON.

So many lines needed to chain request using regular way and this is still 2 request how about 3 or more request? It will be a headache even to reread them.

RxSwift

RxSwift is a library to apply reactive functional programming to our Swift code. To learn more about RFP especially with Rx and all of its operators, you can read it here. With the help of RxSwift, we can easily chain our Alamofire request and make it more readable. We’ll be using a flatMap operator to consume the result and return another Observable Alamofire request.

The first thing that we need to do is install RxAlamofire using Cocoapods or Carthage. In this example, we’ll be using Cocoapods, so add this inside your Podfile

pod 'RxAlamofire'
pod 'SwiftyJSON'

Here we’re not using plain RxSwift but RxAlamofire, a RxSwift wrapper for Alamofire. By adding RxAlamofire, we also add its dependencies: RxSwift & Alamofire. We also added SwiftyJSON to ease the serialization of JSON object. Next, install those pods using pod install, open the Xcode workspace and Build the workspace.

A RxSwift version of the above network requests will be like the following :

_ = json(.get, requestURL1)
    .flatMap { data -> Observable<Any> in
        let jsonData = JSON(data)
        let value = jsonData["key"].stringValue
        return json(.get, "\(requestURL2)?query=\(value)")
    }
    .observeOn(MainScheduler.instance)
    .subscribe { [unowned self] in
        if let data = $0.element {
            let jsonData = JSON(data)
            self.doSomething(jsonData["key"].arrayValue)
        }
    }

Now, the requests chaining is easier to read. This code can be put inside the doNetworkRequest method and this way it is easier to keep track when you need to revisit this code. RxSwift has many operators to help you with this case other than flatMap. Some developers may suggest that you usedo(onNext:), others may suggest using a map operator and many other suggestions. You are free to use any operators as you see fit.

You can clone an example project that shows you how to chain requests like above and populate the result into UITableView.