iosswiftpostswift4

Handling Back To Back HTTP Posts SWIFT 4.0


I currently trying to fetch some data from the server. In order to do so, I have to create a JSON(req1) object and send it as a request to first API. Then, the API returns to me a JSON(res1). From that JSON(res1), I have to extract some data (very lengthy, let's call it Data1) and create another JSON object(req2) and hit another API with it as a request and wait for a response(res2).

Now, it's a back to back function. When I call the first API, it takes a long time to respond and by that time, my second API gets called. Thus, I get an error from the server. How should I over come this?

ALGO:

  1. Call API_A()
  2.  Received JSON_A 
    
  3. Extract JSON_A 4.Call API_B(JASON_A.someparts)
  4.  Received JSON_B
    
  5. Extract JSON_B

Below here is the code:

let json1 = JSON()
let json2 = JSON() //my final result

override func viewDidLoad() {
        super.viewDidLoad()
        firstApiHit { () -> () in
            secondApiHit(jsonV: json1)
        }
    }

func firstApiHit(handleComplete:(()->())){
    let url1 = URL(string : firstApiURL) 
    let json: [String: String] = ["Data1:Data1Rest"]
    let jsonData = try? JSONSerialization.data(withJSONObject: json)
    json1 = httpPost(jsonData: jsonData!, url: url1!)  //hit to the first API!
    handleComplete()
}

func secondApiHit(jsonV : JSON){
    let url1 = URL(string : secondApiURL)
    var value = String()
    extractedValue = String(describing:jsonV["DataX"])
    var json = [String: String]()
    json = ["Data1":extractedValue]
    let jsonData = try? JSONSerialization.data(withJSONObject: json)
    let json2 = httpPost(jsonData: jsonData!, url: url2!) // my final result!
        //Need the json2 as the final Result!!
}
    
func httpPost(jsonData: Data, url: URL) -> JSON {
    if !jsonData.isEmpty {
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.httpBody = jsonData
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        URLSession.shared.getAllTasks { (openTasks: [URLSessionTask]) in
                                       print("open tasks: \(openTasks)")
                                      }
        let task = URLSession.shared.dataTask(with: request) { data, response, error in
                                                          guard let data = data, error == nil else {   
                                                            // check for fundamental networking error
                                                              print("error=\(String(describing: error))")
                                                              return
                                                          }
            if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {           
                    // check for http errors
                print("statusCode should be 200, but is \(httpStatus.statusCode)")
                print("response = \(String(describing: response))")
            }
                                                                  
            let jsonX = JSON(data: data) //extracting the data! 
        }   
        task.resume()
    }
    return jsonM
}

Solution

  • httpPost(...) returns before URLSession.shared.dataTask(...) is finished, because the latter is run asynchronously.

    In firstApiHit(...), you should not call handleComplete(), but pass it on to httpPost(...). You also need to pass the JSON around as parameter.

    override func viewDidLoad() {
        super.viewDidLoad()
        firstApiHit { json in
            secondApiHit(jsonV: json)
        }
    }
    
    func firstApiHit(handleComplete: JSON -> Void){
        ...
        json1 = httpPost(jsonData: jsonData!, url: url1!, handleComplete)
    }
    
    func httpPost(jsonData: Data, url: URL, responseHandler: (JSON) -> Void) {
        let task = URLSession.shared.dataTask(with: request) { data, response, error in
            ...                                   
            let jsonX = JSON(data: data)
            responseHandler(jsonX)
        }   
    }
    

    You definitely need to learn how to use closures and, more specifically, the response handler pattern. Otherwise you'll be in a world of pain again and again.