ClosureChain
简化了 Swift 中顺序异步完成方法的处理。 它为顺序异步方法提供了一种熟悉的 try-catch 模式。
将 ClosureChain
包添加到应用程序的 Package.swift
文件中的依赖项。 将 "x.y.z" 替换为最新的 ClosureChain
版本。
.package(url: "https://github.com/dannys42/ClosureChain.git", from: "x.y.z")
将 ClosureChain
添加到你的 target 的依赖项中
.target(name: "example", dependencies: ["ClosureChain"]),
将 ClosureChain
添加到你的 Podfile 中
pod `ClosureChain`
通常在 Swift 中,网络或其他异步方法会使用完成处理程序来简化工作。 一个典型的方法签名如下所示:
func someAsyncMethod(_ completion: (Data?, Error?)->Void) {
}
但是,当您需要执行多个异步函数,每个函数都依赖于前一次调用的成功数据时,这可能会变得难以管理。
通常,这需要嵌套异步方法或使用状态机。 这两者都难以理解。
Closure Chains 通过允许开发人员将每个异步调用视为可抛出闭包的链接(即链中的链接),并使用单个 catch
闭包来管理任何错误,从而简化了此过程。
let chain = ClosureChain()
chain.try { link in
someAsyncMethod() { data, error in
if let error = error {
link.throw(error) // use `link.throw()` since completion block is not throwable
}
guard let data = data else {
link.throw(Failure.missingDdata) // use `link.throw()` since completion block is not throwable
return
}
// do something with `data`
link.success() // required
}
}
chain.catch { error in
// error handler
}
chain.start() // required to start executing links
请注意熟悉的 try-catch
模式。 但是,try
是在链 chain
上执行的,throw
是在 link
上执行的。 为了方便起见,您可以直接在 try 代码块中使用 Swift throw
命令。
还有两个额外的必需函数
link.success()
来让 ClosureChain
知道异步任务何时完成chain.start()
来启动链的执行。 在启动 .start()
命令之前,不会执行任何链接。当我们只有一个异步操作时,以上内容不是很有用。 但是,如果我们有几个我们希望执行的异步操作该怎么办? 例如,假设我们尝试执行以下任务序列
为简单起见,我们假设我们所有的异步方法都使用 Result
协议。
以下是使用 ClosureChain
的样子
function closureChainExample() {
let chain = ClosureChain()
chain.try { link in
getDataAsync() { result: Result<Data,Error> in // Result type is provided solely for context in this example
switch result {
case .failure(let error):
link.throw(error) // use link.throw() since completion handler is not throwable
case .success(let data):
link.success(data) // Pass `data` to the next link
}
}
}
chain.try { data: Data, link in // `data` type must match prior link.success() (this check is performed at run-time)
convertToUIImage(data) { result: Result<UIImage,Error> in // Result type is provided solely for context in this example
switch result {
case .failure(let error):
link.throw(error) // use link.throw() since completion handler is not throwable
case .success(let uiimage):
link.success(uiimage) // Pass `uiimage` to the next link
}
}
}
chain.try { image: UIImage, link in // `image` type must match prior link.success()
processImage(image) { error: Error? in // Error type is provided solely for context in this example
do {
if let error = error {
throw(error) // can use do-catch to allow `throws` to pass to `link.throw()`
}
link.success() // Go to next link with no passed data
} catch {
link.throw(error)
}
}
}
chain.try { link in // It is safe to ignore the passed parameter from the last `link.success()`
// Notify the user we're done
link.success() // Required even though this is the last link
}
chain.catch { error in
// error handler
}
chain.start() // Required to start executing links
}
注意事项
chain
超出范围。 在调用最后一个链接中的 link.success()
之前,不会从内存中释放 chain
和关联的闭包。如果您的异步方法具有带有单个 Result 参数的完成处理程序,例如
func someAsyncMethod(_ completion: (Result<Data, Error>)->Void) {
}
您可以进一步简化代码
function closureChainExample() {
let chain = ClosureChain()
chain.try { link in
getDataAsync() { result: Result<Data,Error> in // Result type is provided solely for context in this example
link.return(result) // calls link.throw() or link.success() appropriately
}
}
chain.try { data: Data, link in // `data` type must match prior link.success() (this check is performed at run-time)
convertToUIImage(data) { result: Result<UIImage,Error> in // Result type is provided solely for context in this example
link.return(result) // calls link.throw() or link.success() appropriately
}
}
chain.try { image: UIImage, link in // `image` type must match prior link.success()
processImage(image) { result: Result<UIImage,Error> in // Result type is provided solely for context in this example
link.return(result)
}
}
chain.try { link in // It is safe to ignore the passed parameter from the last `link.success()`
// Notify the user we're done
link.success() // Required even though this is the last link
}
chain.catch { error in
// error handler
}
chain.start() // Required to start executing links
}
有关更多信息,请访问我们的 API 参考。
该库是在 Apache 2.0 许可下获得许可的。 完整的许可文本可在 LICENSE 中找到。