Last active
June 6, 2018 05:36
-
-
Save jmcd/7d672b1238eb5d83785a1075b17cb6f7 to your computer and use it in GitHub Desktop.
Chaining async calls in Swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct AsyncTaskChain<Success, Error> { | |
typealias TaskClosure = (Success?, Error?) -> () | |
typealias Task = (TaskClosure) -> () | |
typealias ChainClosure = ([Success], Error?)->() | |
private let tasks: [Task] | |
private let completion: ChainClosure | |
private let previousSuccesses: [Success] | |
init(linkingTasks tasks: [Task], completion: @escaping ChainClosure) { | |
self.init(previousSuccesses: [], tasks: tasks, completion: completion) | |
} | |
private init(previousSuccesses: [Success], tasks: [Task], completion: @escaping ChainClosure) { | |
self.previousSuccesses = previousSuccesses | |
self.tasks = tasks | |
self.completion = completion | |
} | |
func begin() { | |
guard let task = tasks.first else { | |
self.completion(previousSuccesses, nil) | |
return | |
} | |
task { (success, error) in | |
if let success = success { | |
let successes = previousSuccesses + [success] | |
let pendingTasks = Array(tasks[1..<tasks.count]) | |
let shortenedChain = AsyncTaskChain(previousSuccesses: successes, tasks: pendingTasks, completion: self.completion) | |
shortenedChain.begin() | |
} else { | |
self.completion(previousSuccesses, error) | |
} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var chain = AsyncTaskChain(linkingTasks: [ pt0, pt1, pt2 ]) { (successes, error) in | |
if let error = error { | |
print("ERROR \(error)") | |
} | |
print("successes: \(successes)") | |
} | |
chain.begin() | |
/* prints | |
successes: ["str0", "str1", "str2"] | |
*/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var chain = AsyncTaskChain(linkingTasks: [ pt0, pt1_failing, pt2 ]) { (successes, error) in | |
if let error = error { | |
print("ERROR \(error)") | |
} | |
print("successes: \(successes)") | |
} | |
chain.begin() | |
/* prints | |
ERROR Generic | |
successes: ["str0"] | |
*/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
enum Err: Error { | |
case Generic | |
} | |
func pt0(completion: (String?, Error?)->()) { | |
completion("str0", nil) | |
} | |
func pt1(completion: (String?, Error?)->()) { | |
completion("str1", nil) | |
} | |
func pt1_failing(completion: (String?, Error?)->()) { | |
completion(nil, Err.Generic) | |
} | |
func pt2(completion: (String?, Error?)->()) { | |
completion("str2", nil) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment