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.