Chain multiple Alamofire requests
Wrapping other asynchronous stuff in promises works like this:
func myThingy() -> Promise<AnyObject> { return Promise{ fulfill, reject in Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"]).response { (_, _, data, error) in if error == nil { fulfill(data) } else { reject(error) } } }}
Edit: Nowadays, use: https://github.com/PromiseKit/Alamofire-
I wrote a class which handles a chain of request one by one.
I created a class RequestChain
wich takes Alamofire.Request
as parameter
class RequestChain { typealias CompletionHandler = (success:Bool, errorResult:ErrorResult?) -> Void struct ErrorResult { let request:Request? let error:ErrorType? } private var requests:[Request] = [] init(requests:[Request]) { self.requests = requests } func start(completionHandler:CompletionHandler) { if let request = requests.first { request.response(completionHandler: { (_, _, _, error) in if error != nil { completionHandler(success: false, errorResult: ErrorResult(request: request, error: error)) return } self.requests.removeFirst() self.start(completionHandler) }) request.resume() }else { completionHandler(success: true, errorResult: nil) return } }}
And I use it like this
let r1 = Alamofire.request(Router.Countries).responseArray(keyPath: "endpoints") { (response: Response<[CountryModel],NSError>) in print("1")}let r2 = Alamofire.request(Router.Countries).responseArray(keyPath: "endpoints") { (response: Response<[CountryModel],NSError>) in print("2")}let r3 = Alamofire.request(Router.Countries).responseArray(keyPath: "endpoints") { (response: Response<[CountryModel],NSError>) in print("3")}let chain = RequestChain(requests: [r1,r2,r3])chain.start { (success, errorResult) in if success { print("all have been success") }else { print("failed with error \(errorResult?.error) for request \(errorResult?.request)") }}
Importent is that you are telling the Manager to not execute the request immediately
let manager = Manager.sharedInstance manager.startRequestsImmediately = false
Hope it will help someone else
Swift 3.0 Update
class RequestChain { typealias CompletionHandler = (_ success:Bool, _ errorResult:ErrorResult?) -> Void struct ErrorResult { let request:DataRequest? let error:Error? } fileprivate var requests:[DataRequest] = [] init(requests:[DataRequest]) { self.requests = requests } func start(_ completionHandler:@escaping CompletionHandler) { if let request = requests.first { request.response(completionHandler: { (response:DefaultDataResponse) in if let error = response.error { completionHandler(false, ErrorResult(request: request, error: error)) return } self.requests.removeFirst() self.start(completionHandler) }) request.resume() }else { completionHandler(true, nil) return } }}
Usage Example Swift 3
/// set Alamofire default manager to start request immediatly to false SessionManager.default.startRequestsImmediately = false let firstRequest = Alamofire.request("https://httpbin.org/get") let secondRequest = Alamofire.request("https://httpbin.org/get") let chain = RequestChain(requests: [firstRequest, secondRequest]) chain.start { (done, error) in }
You have multiple options.
Option 1 - Nesting Calls
func runTieredRequests() { let putRequest = Alamofire.request(.PUT, "http://httpbin.org/put") putRequest.response { putRequest, putResponse, putData, putError in let getRequest = Alamofire.request(.GET, "http://httpbin.org/get") getRequest.response { getRequest, getResponse, getData, getError in // Process data // Reload table } }}
This is definitely the approach I would recommend. Nesting one call into another is very simple and is pretty easy to follow. It also keeps things simple.
Option 2 - Splitting into Multiple Methods
func runPutRequest() { let putRequest = Alamofire.request(.PUT, "http://httpbin.org/put") putRequest.response { [weak self] putRequest, putResponse, putData, putError in if let strongSelf = self { // Probably store some data strongSelf.runGetRequest() } }}func runGetRequest() { let getRequest = Alamofire.request(.GET, "http://httpbin.org/get") getRequest.response { [weak self] getRequest, getResponse, getData, getError in if let strongSelf = self { // Probably store more data strongSelf.processResponse() } }}func processResponse() { // Process that data}func reloadData() { // Reload that data}
This option is less dense and splits things up into smaller chunks. Depending on your needs and the complexity of your response parsing, this may be a more readable approach.
Option 3 - PromiseKit and Alamofire
Alamofire can handle this pretty easily without having to pull in PromiseKit. If you really want to go this route, you can use the approach provided by @mxcl.