How to optimize asynchronous request chain in Swift

I have code that runs a chain like A-> B-> C , and I use URLSession , all requests are executed in the correct order and with the expected behavior. But I am wondering how I can optimize this chain because it looks quite complex and cannot be reused. I am looking for a suggestion on how I can make this chain more flexible.

My code is:

 URLSession.shared.dataTask(with: URLRequest(url: URL(string: "first")!)){ data , res , err in let second = URLRequest(url: URL(string: "second")!) URLSession.shared.dataTask(with: second){ data , res , err in let third = URLRequest(url: URL(string: "second")!) URLSession.shared.dataTask(with:third){ data , res , err in }.resume() }.resume() }.resume() 
+5
source share
2 answers

As @ Paulw11 said:

PromiseKit + PMKFoundation

 import PromiseKit import PMKFoundation let session = URLSession.shared firstly { session.dataTask(with: URLRequest(url: URL(string: "first")!)) } .then { data in session.dataTask(with: URLRequest(url: URL(string: "second")!)) } .then { data in session.dataTask(with: URLRequest(url: URL(string: "third")!)) } .then { data -> () in // The data here is the data fro the third URL } .catch { error in // Any error in any step can be handled here } 

With a repeat of 1 (and only 1) you can use recover . recover is similar to catch , except it is expected that the previous then can be repeated. However, this is not a loop and is executed only once.

 func retry(url: URL, on error: Error) -> Promise<Data> { guard error == MyError.retryError else { throw error } // Retry the task if a retry-able error occurred. return session.dataTask(with: URLRequest(url: url)) } let url1 = URL(string: "first")! let url2 = URL(string: "second")! let url3 = URL(string: "third")! let session = URLSession.shared firstly { session.dataTask(with: URLRequest(url: url1)) } .then { data in session.dataTask(with: URLRequest(url: url2)) } .recover { error in retry(url: url2, on: error) } .then { data in session.dataTask(with: URLRequest(url: url3)) } .recover { error in retry(url: url3, on: error) } .then { data -> () in // The data here is the data fro the third URL } .catch { error in // Any error in any step can be handled here } 

NOTE. To make this work without specifying return types and the need for a return , I need then and recover be exactly 1 line. Therefore, I create methods for processing.

+3
source

In fact, you can use the dependencies using OperationQueues, as shown below:

 func operationQueueWithBlockandCancel(){ let mainQueue = OperationQueue.main let operationBlock1 = BlockOperation() let operationBlock2 = BlockOperation() let operationBlock3 = BlockOperation() operationBlock1.addExecutionBlock { //Any task } operationBlock2.addExecutionBlock { //Any task } operationBlock3.addExecutionBlock { //Any task } //Add dependency as required operationBlock3.addDependency(operationBlock2) operationBlock2.addDependency(operationBlock1) opQueue.addOperations([operationBlock2,operationBlock1,operationBlock3,], waitUntilFinished: false) } 
+5
source

Source: https://habr.com/ru/post/1266681/


All Articles