注册
iOS

Swift 中async/await 简单使用

在 Swift 5.5 中,终于加入了语言级别的异步处理 async/await,这应该会让用回调闭包写异步调用方法时代彻底结束了!



这篇文章就简单总结一下这个功能使用吧。


异步函数


所谓异步,是相对于同步而言,这是一种执行任务的方式,同步的执行任务,任务需要一个一个的顺序执行,前边的好了,后边的才能运行。而异步就不是这样,它不需要等待当前任务执行完成,其他任务就可以执行。


在 Swift 5.5 中,添加了 async 关键字,标记这个函数是一个异步函数。

func getSomeInfo() async -> String { ... }
/// 可以抛出错误的异步函数
func getSomeInfoWithError() async throws -> String { ... }


这里需要注意的是,如果我们想调用异步函数,就必须在其他异步函数或者闭包里面使用 await关键字。

func runAsyncFunc() async {
let info = await getSomeInfo()
...
}

func runAsyncErrorFunc() async throws {
let info = try await getSomeInfoWithError()
...
}

实际使用异步函数的时候,我们是无法在同步函数里使用的,这时Swift会报错。要使用的话,就需要我们要提供了一个异步执行的环境 Task

func someFunc() {
Task {
runAsyncFunc()
}
}


异步序列


如果一个序列中的每个信息都是通过异步获取的,那么就可以使用异步序列的方式遍历获取。前提是序列是遵守AsyncSequence协议,只要在for in 中添加 await关键字。

let asyncItems = [asyncItem1, asyncItem2, asyncItem3]
for await item in asyncItems { ... }

多个异步同时运行


这个可以使用叫做异步绑定的方式,就是在每个存储异步返回信息的变量前边添加async

async let a = getSomeInfo()
async let b = getSomeInfo()
async let c = getSomeInfo()
let d = await [a, b, c]
...

这时运行的情况就是 a b c 是同时执行的,也就是所说的并行执行异步任务,即并发。


结构化并发


上边在提到在同步函数中使用异步函数,我们需要添加一个Task,来提供异步运行的环境。 每个 Task 都是一个单独任务,里面执行一些操作,这操作可以是同步也可以是异步。多个任务执行时,可以把它们添加到一个任务组TaskGroup中,那么这些任务就有了相同的父级任务,而这些任务Task又可以添加子任务,这样下来,任务之间就有了明确的层级关系,这也就是所谓的结构化并发


任务和任务组


任务组可以更为细节的处理结构化并发,使用方式如下,就在任务组中添加单个任务即可。

func someTasksFunc() {
Task {
await withTaskGroup(of: String.self) { group in
group.addTask {
let a = await getSomeInfo()
...
}
group.addTask {
let b = await getSomeInfo()
...
}
}
}
}

从运行的方式来说,这种使用任务组的情况和异步绑定的效果一样,简单的异步任务,完全可以使用异步绑定的方式。而任务和任务组是为更为复杂的并发情况提供支持,比如任务的优先级,执行和取消等。


如果异步函数是可抛出错误的,使用withThrowingTaskGroup就行。


解决数据竞争的Actor


在并发过程中,对于同一属性数据的读取或者写入,有时会有奇怪的结果,这些由于在不同的线程,同时进行了操作。消除这种问题的方式,就是使用 Swift 提供的 Actor类型。 一个和类差不多的类型,但是对自身可变内容进行了隔离。

actor SomeInfo {
var info: String
}

外部在访问其info属性时,actor 做了隔离,每次只能一个线程访问,直接访问就会报错。而且外部不能进行修改,只有内部才能修改。


外部访问方式就是需要异步执行,在异步环境中,添await

let content = SomeInfo(info: "abc")
let info = await content.info)
...

总结


以上就是Swift 5.5 async/await的简单使用了。了解了这些,就可以日常开发中替代闭包回调,告别回调地狱和处理不完的 completionHandler了。😎
目前官方已经在已有闭包回调处理异步的地方,都增加async异步版本,自行查看文档了解吧。。


另外附上一些很有帮助的文章地址,这些地方都有更为详尽的说明,参考学习起来!


Swift 5.5 有哪些新功能?


http://www.hackingwithswift.com/articles/23…


Swift 并发初步


onevcat.com/2021/07/swi…


并发


swiftgg.gitbook.io/swift/swift…


作者:WeiYou
链接:https://juejin.cn/post/7250375035634090043
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

0 个评论

要回复文章请先登录注册