Ax 是一个用于以有组织的方式控制异步执行流程的 Swift 库。受到了 async 库 的启发。
例如,当您的异步调用相互依赖时,那么一个简单的解决方案就是在下面的例子中这样嵌套调用
runAsync(afterSeconds: 2, completion: {
let dataFromTask1 = 1
self.runAsync(afterSeconds: 2, completion: {
let dataFromTask2 = 2
self.runAsync(afterSeconds: 2, completion: {
let dataFromTask3 = 3
self.runAsync(afterSeconds: 2, completion: {
let dataFromTask4 = 4
print(dataFromTask1) // 1
print(dataFromTask2) // 2
print(dataFromTask3) // 3
print(dataFromTask4) // 4
})
})
})
})
嵌套异步调用是编程中的常见问题,社区将其命名为:回调地狱,“地狱之塔”。
我们应该避免这种代码,因为它可能导致一些真正混乱、难以阅读的代码,这是不良的编程习惯。
这时就轮到 Ax 出场,它可以帮助您以线性方式调用异步调用,给人一种运行同步调用的印象
import Ax
var dataFromTask1 = 0
var dataFromTask2 = 0
var dataFromTask3 = 0
var dataFromTask4 = 0
Ax.serial(
tasks: [
{ done in
self.runAsync(afterSeconds: 2) {
dataFromTask1 = 1
done(nil)
}
},
{ done in
self.runAsync(afterSeconds: 2) {
dataFromTask2 = 2
done(nil)
}
},
{ done in
self.runAsync(afterSeconds: 2) {
dataFromTask3 = 3
done(nil)
}
},
{ done in
self.runAsync(afterSeconds: 2) {
dataFromTask4 = 4
done(nil)
}
}
],
result: { error in // feedback closure
print(dataFromTask1) // outputs 1
print(dataFromTask2) // outputs 2
print(dataFromTask3) // outputs 3
print(dataFromTask4) // outputs 4
}
)
done
是一个接收 NSError?
值的闭包,当 done
被调用并传入 nil
时,意味着任务运行成功;另一方面,如果 done
被调用并传入一个 NSError
值,则忽略所有后续任务,并立即用传递给 done
的错误值执行 result
闭包。tasks
和 result
中的 闭包 以 DispatchQoS.QoSClass.background
模式运行,如果您需要,例如,在主线程中调用结果,则由您自己决定。最初支持的函数包括
该函数帮助你以顺序方式执行异步调用,按照有序的方式进行,首先运行第一个调用,完成后,然后运行下一个调用,以此类推。
示例
import Ax
var authorId = ""
var authorBooks = [Book]()
Ax.serial(
tasks: [
{ done in
self.getAuthorBy(name: "J. K. Rowling") { error, author in
guard let author = author else {
done(NSError(domain: "AppDomain", code: 434, userInfo: [NSLocalizedDescriptionKey: "didn't get author"]))
return
}
authorId = author.id
done(error)
}
},
{ done in
self.getBooksBy(authorId: authorId, completion: { (error, books: [Book]) in
authorBooks = books
done(error)
})
}
],
result: { error in
if let error = error {
print(error)
return
}
print(authorBooks) // [Book(name: "Harry Potter and the Philosopher\'s Stone"), Book(name: "Harry Potter and the Chamber of Secrets")]
}
)
帮助你以并行方式执行异步调用,当你需要执行许多固定调用时,该功能将帮助你,但这些调用是否同时运行并不重要。
示例
import Ax
let userId = "1"
let profileImageURL = "https://unsplash.it/100"
var userFound: User?
var userImage: UIImage?
Ax.parallel(
tasks: [
{ done in
self.getUserBy(id: userId) { error, user in
guard let user = user else {
done(NSError(domain: "AppDomain", code: 434, userInfo: [NSLocalizedDescriptionKey: "No user found."]))
return
}
userFound = user
done(error)
}
},
{ done in
self.getProfileImageBy(url: profileImageURL) { error, image in
guard let image = image else {
done(NSError(domain: "AppDomain", code: 435, userInfo: [NSLocalizedDescriptionKey: "Image not found."]))
return
}
userImage = image
done(error)
}
}
],
result: { error in
if let error = error {
print(error)
return
}
print(userFound!) // User(name: "Walter While")
print(userImage!) // <UIImage: 0x618000095a90>, {100, 100}
}
)
Ax通过CocoaPods提供。要安装它,只需将以下行添加到您的Podfile中
pod "Ax"
安装后,只需将其导入到您正在工作的文件中
import Ax
Wilson Balderrama,[email protected]
Ax可供MIT许可下使用。有关更多信息,请参阅LICENSE文件。