TheChain
TheChain 帮助你编写更清晰、更易于阅读的异步代码
override func viewDidLoad() {
super.viewDidLoad()
downloadImageData().onStart {
print("Downloading started")
}.onCompletion {
print("Downloading finished")
}.then(
cacheDownloadedData
).then(
readImageFromCache
).catch { (error) in
print("❌ Failed to load image: \(error.localizedDescription)")
}.finally(on: .main) { (image) in
self.imageView.image = image
}
}
// MARK: - Async
private func downloadImageData() -> Link<Data> {
return URLSession.shared.dataTaskLink(with: "https://lorempixel.com/1000/1000/")
}
private func cacheDownloadedData(_ data: Data) -> Link<Void> {
return Link(on: .global(), {
let url = try URL.imageDataFileUrl.orThrow(Error.fileUrlIsNil)
try data.write(to: url)
})
}
private func readImageFromCache() -> Link<UIImage> {
return Link(onGlobalQueue: {
let url = try URL.imageDataFileUrl.orThrow(Error.fileUrlIsNil)
let data = try Data(contentsOf: url)
return try UIImage(data: data).orThrow(Error.unableToInitImage)
})
}
基本用法
你只需要创建一个新的带有所需结果类型的 Link
对象,运行异步代码,并在异步工作完成后传递结果或错误。
func asyncMethod() -> Link<String> {
let link = Link<String>()
DispatchQueue.global().async {
//Some async work goes here
link.finish("Async work result")
//or
//link.throw(Error.someError)
}
return link
}
func someMethod() {
asyncMethod().catch { (error) in
// Handle error
}.finally { (result) in
// Handle the String result
}
}
链式调用
你可以像这样使用 Links
创建一个链
func asyncFoo() -> Link<String> {
...
}
func asyncBar(_ input: String) -> Link<Double> {
...
}
func asyncBaz(_ input: Double) -> Link<Bool> {
...
}
asyncFoo().then(asyncBar).then(asyncBaz).catch { (error) in
// Handle error
}.finally { (result) in
// Handle the Bool result
}
扩展
TheChain 带有一些实用的扩展,可以帮助你编写更紧凑、无样板代码。
dispatchQueue
func readImageFromCache() -> Link<UIImage> {
return Link(onGlobalQueue: {
let url = try URL.imageDataFileUrl.orThrow(Error.fileUrlIsNil)
let data = try Data(contentsOf: url)
return try UIImage(data: data).orThrow(Error.unableToInitImage)
})
}
而不是
func readImageFromCache() -> Link<UIImage> {
let link = Link<UIImage>()
DispatchQueue.global().async {
guard let url = URL.imageDataFileUrl else {
return link.throw(Error.fileUrlIsNil)
}
do {
let data = try Data(contentsOf: url)
guard let image = UIImage(data: data) else {
return link.throw(Error.unableToInitImage)
}
link.finish(image)
} catch {
link.throw(error)
}
}
return link
}
URLSession
func loadPosts() -> Link<[Post]> {
return URLSession.shared.dataTaskLink(with: "https://jsonplaceholder.typicode.com/posts")
}
而不是
func loadPosts() -> Link<[Post]> {
let link = Link<[Post]>()
guard let url = URL(string: "https://jsonplaceholder.typicode.com/posts") else {
return link.throw(Error.unableToInitUrl)
}
URLSession.shared.dataTask(with: URLRequest(url: url)) { (data, _, error) in
if let data = data {
do {
let posts = try JSONDecoder().decode([Post].self, from: data)
link.finish(posts)
} catch {
link.throw(error)
}
} else if let error = error {
link.throw(error)
}
}.resume()
return link
}
安装
TheChain可通过CocoaPods获取。要安装,只需将以下行添加到您的Podfile中
pod 'TheChain'
许可证
TheChain遵循MIT许可证。有关更多信息,请参阅LICENSE文件。