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:
Received JSON_A
Received 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
}
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.