Leave a rating/review
Refresh your browser to make sure the course server is running or restart the server in Terminal
Continue with your project from the previous episode or open the starter project for this episode.
Build and run the project.
To complete the challenge in the previous episode, you downloaded and displayed this list of files.
Serial vs Concurrent
When you store files on a cloud server, you usually want to know how much storage you’ve used and whether you have duplicate files. This “cloud server” has an endpoint to supply this information.
In SuperStorageModel, locate the status() method:
func status() async throws -> String {
guard let url = URL(string: "http://localhost:8080/files/status") else {
throw "Could not create the URL."
}
return ""
}
Replace the dummy return statement with the usual code:
let (data, response) = try await URLSession.shared.data(from: url) // fetch the data
guard (response as? HTTPURLResponse)?.statusCode == 200 else { // check the statusCode
throw "The server responded with an error."
}
return String(decoding: data, as: UTF8.self)
The returned data is just a String encoded with Unicode UTF8.
Now, go to ListView and call this method inside the do closure, after the call to availableFiles():
do {
files = try await model.availableFiles()
🟩status = try await model.status()
This course is about concurrency, and your brain might now be telling you something’s not quite right about what you just did. Hold that thought until you’ve checked this code works. Build and run.
Below the list of files is a server usage message, with random values for percentage and number of duplicate files.
Grouping async calls
OK, now back to that do closure.
This first try await means the call to status() doesn’t start until the call to availableFiles() completes.
Both calls are asynchronous, and they call different server endpoints. They could run in the opposite order, or they could run at the same time. How do you make this happen?
Replace those two lines with these:
async let files = try model.availableFiles()
async let status = try model.status()
Option-click files to see it’s now a local constant, but more, it’s an async let constant.
An async let constant is like a promise that a value or an error will become available. The async in async let means you must use await to access the promised value.
Next, you need to group these two async calls:
let (filesResult, statusResult) = try await (files, status)
You use tuples to group the two async let constants and the two results. If you have to await more than 2 or 3 results, you can use an array.
Option-click filesResult and statusResult to see they’re normal let constants.
So now you can assign them to the view’s State properties, to update the view.
Add these lines at the end of the do closure:
self.files = filesResult
self.status = statusResult
You set the State properties of ListView. Build and run.
Now, the server requests run at the same time, so the UI becomes ready for the user a little faster.
It’s pretty amazing that the same async, await and let syntax lets you run non-blocking asynchronous code serially and also concurrently.
You’re displaying server status in the list view. Next up: You’ll start implementing the download view.