Swift 的 async 和 await。
使用方法
等待结果
也许我本末倒置了,但... 对于下一节中的所有函数,您都可以以相同的方式等待返回值
func someFuncRunningInBackground() throws {
let value = try await { self.someLongRunningAsynchronousFunc() }
// do something with the returned value...
}
您还可以仅在需要时使用结果
func someFuncRunningInBackground() throws {
// the task starts immediately
let task = self.someLongRunningAsynchronousFunc()
// do other things, the task is running...
// continue doing other things...
// the task can be still running or maybe it is already finished, who knows?
//
let value = try await(task)
// do something with the returned value...
}
创建异步任务
您可以在 async
闭包中简单返回所需的值。
func someLongRunningAsynchronousFunc -> Task<SomeValuableValue> {
return async {
let value = self.createSomeValuableValue()
// some long running code here...
return value
}
}
但是,如果您正在调用具有完成处理程序的方法,您可能需要一个不同的闭包签名,将其任务本身作为参数,并在工作完成时调用其 finish(with:)
方法。
func someLongRunningAsynchronousFunc -> Task<SomeValuableValue> {
return async { task in
self.getSomeValuableValue(completionHandler: { value in
task.finish(with: value)
})
}
}
如果完成处理程序有一个错误作为附加参数,您也可以将其传递给 finish
方法(它将在等待任务结果时在 try
语句中处理)。
func someLongRunningAsynchronousFunc -> Task<SomeValuableValue> {
return async { task in
self.getSomeValuableValue(completionHandler: { value, error in
task.finish(with: value, or: error)
})
}
}
使用 DispatchQueue 和 OperationQueue 创建任务
您还可以使用添加到 DispatchQueue
和 OperationQueue
的便利方法来创建任务
func calculate() -> Double {
// using DispatchQueue
let someCalculatedValue = await(DispatchQueue.global(qos: .background).async {
var value: Double = 0
// do some long running calculation here
return value
} as NonFailableTask<Double>)
// using OperationQueue
let operationQueue = OperationQueue()
operationQueue.qualityOfService = .background
let operationTask = operationQueue.addOperation {
var value: Double = 0
// do some long running calculation here
return value
} as NonFailableTask<Double>
// using the results
return someCalculatedValue * await(operationTask)
}
取消任务
您可以使用任务的 cancel()
方法在队列中之后取消一个任务。实际上何时取消取决于其内容实现。
在 AlecrimAsyncKit 中取消任务与用一个带有 NSCocoaErrorDomain
和 NSUserCancelledError
参数的 NSError
完成任务非常相似。但如果您使用 cancel()
,可以使用提供的代码块触发取消操作。
您可以添加要在任务以此方式取消时执行的取消代码块
func someLongRunningAsynchronousFunc -> Task<SomeValuableValue> {
return async { task in
let token = self.getSomeValuableValue(completionHandler: { value, error in
task.finish(with: value, or: error)
})
// add a closure to be executed when and if the task is cancelled
task.cancellation += {
token.invalidate()
}
}
}
当然,这只能在您使用“扩展”的异步闭包签名时完成,因为您可能需要 task
参数。
当可能时,框架将尝试为子任务“继承”取消操作。这意味着如果父任务被取消,在其实现中开始的任务也可能被取消,而无需进行重大干预。
主线程
由于 await
函数阻塞当前线程,因此您只能在后台 DispatchQueue
、OperationQueue
或 Thread
上等待异步函数。但在主线程上您可以做以下操作
func someFuncRunningInTheMainThread() {
//
self.activityIndicator.startAnimating()
// start the background task
self.someLongRunningAsynchronousFunc()
.then { value in
// when the background work is done,
// do something with the returned value in the main thread
}
.catch { error in
// do a nice error handling
}
.finally {
self.activityIndicator.stopAnimating()
}
}
所有方法 (then
、catch
、cancelled
和 finally
)都是可选的。当指定时,无论任务是否被取消或是否发生错误,相关的闭包都会始终调用。
非失败任务
如果您阅读了框架的代码,您会找到 NonFailableTask<Value>
类。这种类型的任务不会失败(有点)。实际上它可能失败,但不应失败。
与可失败的任务相比,主要区别在于在等待非失败任务的结果时不需要 try
。非失败任务也不能取消。
只有在您确定该任务不会失败时才请使用此类型。如果它失败了,那么程序将崩溃。
依赖、条件和观察者
上一个版本基于WWDC 2015的第226场会议(“高级NSOperations”)的观察者和条件。这使得框架变得不必要地复杂。如果您现在就需要此功能,可以使用 AlecrimAsyncKit 版本3.x。
在4.0版本中,框架引入了“依赖”的概念,并实现了新的“条件”类型。观察者可能会在未来的版本中重新出现。但没有保证。
贡献
如果您有任何问题或需要更多信息,请使用提供的GitHub链接打开问题。
您也可以通过修复错误或创建新功能来贡献。在这种情况下,请将您的请求提交到该存储库,因为我没有太多时间去“寻找”尚未提交的补丁。
- master - 生产分支。克隆或分叉此存储库以获取最新版本。
- develop - 活动开发分支。《拉取请求》[点击此处] 应该指向此分支。
联系作者
许可协议
AlecrimAsyncKit 在MIT许可协议下发布。有关更多信息,请参阅LICENSE。