来自JavaScript世界使用async javascript promises,我相信在Swift中使用GCD异步队列也是如此。
您能否指出一个示例,其中队列中指定了2到3个异步函数,其中一个异步操作将结果提供给第二个,第二个将结果提供给第三个(通常称为管道结果)和然后最后是一个结果和错误处理程序。
所有函数都按设计限制为单个参数。
如果在功能2期间发生任何错误,则跳过功能3并将错误直接传递给错误处理程序。
寻找原生解决方案,而不是任何第三方Promise或Monad库。
欣赏swift 3.0代码。
编辑。还从示例中了解到,步骤更像是GCD中的手动线性路径,其中开发人员是下一次的馈送结果并且每次都检查错误,使用Function Compositions可以进行任何功能编程吗?
答案 0 :(得分:2)
我已通过支持请求与Apple联系,他们将我转介到此WWDC15视频Advance NSOperations。
我没有看到如何将结果从一个子操作传递到另一个子操作,现在基于此视频,如果有人可以编写一些全面的示例代码,其中一个例程执行后将结果传递给下一个,我&# 39; d接受答案。
答案 1 :(得分:2)
标准库中没有对此的支持,可能不会有一段时间。有很棒的第三方库,但如果你不想要那些,你可以自己定义一个最小值(我在这里使用Swift 3):
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))
}
})
}
}
用法示例:
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)")
}
}
高级用法示例:
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)
}
}