Last active
May 16, 2023 08:52
-
-
Save Gujci/5628f873ffe6365ead9da3f689440a7c to your computer and use it in GitHub Desktop.
swift implementation of the famous async-waterfall
This file contains 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
public class Async { | |
/// Throw version implementation of waterfall | |
/// | |
/// - Parameters: | |
/// - initialValue: initial passed value of the chain | |
/// - chain: chain of closures to process | |
/// - end: last callback. Called after the chain finished or in an error occures | |
/// - Throws: Any error that one of the chain elements throwed | |
/// | |
/// - Note: Each callback should be called only once during executon | |
class func waterfall(_ initialValue: Any? = nil,_ chain:[(@escaping (Any?) throws -> (), Any?) throws -> ()],end: @escaping (Any?) -> () ) throws { | |
guard let function = chain.first else { | |
end(initialValue) | |
return | |
} | |
try function({ (newResult: Any?) in try waterfall(newResult, Array(chain.dropFirst()), end: end) } , initialValue) | |
} | |
/// Error first callback | |
/// The problem with throwing are async, non-rethowing functions 😨 .. so we need both | |
/// | |
/// - Parameters: | |
/// - initialValue: initial passed value of the chain | |
/// - chain: chain of closures to process | |
/// - end: last callback. Called after the chain finished or in an error occures | |
/// | |
/// - Note: Each callback should be called only once during executon | |
class func waterfall(_ initialValue: Any? = nil,_ chain:[(@escaping (Error?, Any?) -> (), Any?) -> ()],end: @escaping (Error?, Any?) -> () ) { | |
guard let function = chain.first else { | |
end(nil, initialValue) | |
return | |
} | |
function({ (err: Error?, newResult: Any?) in | |
if let err = err { | |
end(err, nil) | |
return | |
} | |
waterfall(newResult, Array(chain.dropFirst()), end: end) | |
}, initialValue) | |
} | |
/// Combined | |
/// Each chain function can throw, but the waterfall will get the error in the end callback, best use if all async calls are rethrowing, and the result and error has to be handled at the same place | |
/// | |
/// - Parameters: | |
/// - initialValue: initial passed value of the chain | |
/// - chain: chain of closures to process | |
/// - end: last callback. Called after the chain finished or in an error occures | |
/// | |
/// - Note: Each callback should be called only once during executon | |
class func waterfall(_ initialValue: Any? = nil,_ chain:[(@escaping (Any?) -> (), Any?) throws -> ()],end: @escaping (Error?, Any?) -> () ) { | |
guard let function = chain.first else { | |
end(nil, initialValue) | |
return | |
} | |
do { | |
try function({ (newResult: Any?) in waterfall(newResult, Array(chain.dropFirst()), end: end) }, initialValue) | |
} | |
catch let error { | |
end(error, nil) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment