GCD template for a chain of asynchronous operations in pipelining results

Coming from the world of JavaScript using async javascript promises, and I believe the same thing is done using asynchronous GCD queues in Swift.

Can you tell me an example where 2 to 3 asynchronous functions are specified in the queue, with one async operation giving the result to the second, and the second giving the result to the third (usually called pipelined results) and then, finally, the result and error handler.

All functions are limited to one design argument.

If any error allows you to speak during function 2, function 3 is skipped and the error is passed directly to the error handler.

We are looking for a native solution instead of any third-party Promise or Monad .

Check out the fast version 3.0 code.

Change In addition, the example shows that the steps are more like a manual linear path in GCD, where the developer is the only result of filing for the next and checking the error each time, is any functional programming possible using Function Composition ?

I want to avoid Pyramid of Doom and am looking for linear asynchronous programming .

+5
source share
2 answers

I asked Apple for support, and they directed me to this WWDC15 video Pre NSOperations .

I was not able to see how to transfer the results from one auxiliary operation to another, now based on this video, if someone can write some comprehensive sample code, where one subroutine, after transferring the results to the next, I would accept the answer.

+2
source

There is no support in the standard library, and probably will not for some time. There are great third-party libraries, but if you don't want them, you can define the minimum yourself (I use Swift 3 here):

enum Result<R> { case Success(R) case Failure(ErrorProtocol) } typealias Async<A, B> = (a: A, handler: (Result<B>) -> Void) -> Void infix operator • { associativity right precedence 190 } func •<A, B, C>(f: Async<A, B>, g: Async<B, C>) -> Async<A, C> { return { a, handler in f(a: a, handler: { result in switch result { case .Success(let b): g(a: b, handler: handler) case .Failure(let e): handler(.Failure(e)) } }) } } 

Usage example:

 func f(n: Int, h: (Result<String>) -> ()) { h(.Success(n.description)) } func g(s: String, h: (Result<Int>) -> ()) { h(.Success(s.characters.count)) } let chained = f • g chained(a: 10) { result in switch result { case .Success(let r): print("Success: \(r)") case .Failure(let e): print("Error: \(e)") } } 

Extended usage example:

 enum Error : ErrorProtocol { case NoResult case StringDecoding } extension URLSession { func getData(with url: URL, completionHandler: (Result<(Data, URLResponse)>) -> Void) { let task = dataTask(with: url) { (data, response, error) in if let error = error { completionHandler(.Failure(error)) } else if let data = data, response = response { completionHandler(.Success((data, response))) } else { completionHandler(.Failure(Error.NoResult)) } } task.resume() } } func decode(d: (Data, URLResponse), handler: (Result<String>) -> Void) { DispatchQueue(label: "async").async{ if let string = String(data: d.0, encoding: .utf8) { handler(.Success(string)) } else { handler(.Failure(Error.StringDecoding)) } } } let getString = URLSession.shared().getData • decode getString(a: URL(string: "https://www.reddit.com")!) { result in switch result { case .Success(let string): print(string) case .Failure(let e): print(e) } } 
+2
source

All Articles