Defining and Calling Asynchronous Functions
We use async
keyword in place of before return arrow in function definition to make a function as a Asynchronour Function.
Just like throwing functions
, and wa wanna a function is both asynchronous and throwing, we write async
before throwing
.
func listPhotos(inGallery name: String) async -> [String] {
let result = // ... some asynchronous networking code ...
return result
}
func listPhotos2(inGallery name: String) async throws -> [String] {
let result = // ... some asynchronous networking code ...
return result
}
And we use await
keyword to describe we need to wait a return value whthin a function untill it returns.
let photoNames = await listPhotos(inGallery: "Summer Vacation")
let sortedNames = photoNames.sorted()
let name = sortedNames[0]
let photo = await downloadPhoto(named: name)
show(photo)
await
will suspend the code that is excuting.
Calling Asynchronous Functions in Parallel
If we want to call a function in parallel, just like dispatch.async
, we don’t want a function to suspend the code, but we need the async characteristic, we can use async
keyword to decorate a value.
async let firstPhoto = downloadPhoto(named: photoNames[0])
async let secondPhoto = downloadPhoto(named: photoNames[1])
async let thirdPhoto = downloadPhoto(named: photoNames[2])
let photos = await [firstPhoto, secondPhoto, thirdPhoto]
show(photos)
The example above shows a circumstance just like using dispatch,group
.
Tasks and Task Groups
There are interesting thing that is the task in swift.
We can incoporate Task
and async
there two characteristics to do a asynchronous task surprisingly easy.
We can handle a group of tasks even.
await withTaskGroup(of: Data.self) { taskGroup in
let photoNames = await listPhotos(inGallery: "Summer Vacation")
for name in photoNames {
taskGroup.async { await downloadPhoto(named: name) }
}
}
let newPhoto = // ... some photo data ...
let handle = Task {
return await add(newPhoto, toGalleryNamed: "Spring Adventures")
}
let result = await handle.value
And we can control each task by change its status.
Actors
Actor is just like Class
, we can define a new actor with properties and functions by using actor
keyword
actor TemperatureLogger {
let label: String
var measurements: [Int]
private(set) var max: Int
init(label: String, measurement: Int) {
self.label = label
self.measurements = [measurement]
self.max = measurement
}
}
But actor is much safer than class in asynchronous function since it only agree one operation on its state at a time.
And for its private
property, we must use await
to access it, which is called as actor isolation.
Let’s think!