< How to handle different result types in a task group | How to make async command-line tools and scripts > |
Updated for Xcode 14.2
Swift’s async let
, Task
, and task groups all solve a similar problem: they allow us to create concurrency in our code so the system is able to run them efficiently. Beyond that, the way they work is quite different, and which you’ll choose depends on your exact scenario.
To help you understand how they differ, and provide some guidance on where each one is a good idea, I want to walk through the key behaviors of each of them.
First, async let
and Task
are designed to create specific, individual pieces of work, whereas task groups are designed to run multiple pieces of work at the same time and gather the results. As a result, async let
and Task
have no way to express a dynamic amount of work that should run in parallel.
For example, if you had an array of URLs and wanted to fetch them all in parallel, convert them into arrays of weather readings, then average them to a single Double
, task groups would be a great choice because you won’t know ahead of time how many URLs are in your array. Trying to write this using async let
or Task
just wouldn’t work, because you’d have to hard-code the exact number of async let
lines rather than just loop over an array.
Second, task groups automatically let us process results from child tasks in the order they complete, rather than in an order we specify. For example, if we wanted to fetch five pieces of data, task groups allow us to use group.next()
to read whichever of the five comes back first, whereas using async let
and Task
would require us to await values in a specific, fixed order.
That alone is a helpful feature of task groups, but in some situations it goes from helpful to crucial. For example, if you have three possible servers for some data and want to use whichever one responds fastest, task groups are perfect – you can use addTask()
once for each server, then call next()
only once to read whichever one responded fastest.
Third, although all three forms of concurrency will automatically be marked as cancelled if their parent task is cancelled, only Task
and task group can be cancelled directly, using cancel()
and cancelAll()
respectively. There is no equivalent for async let
.
Fourth, because async let
doesn’t give us a handle to the underlying task it creates for us, it’s not possible to pass that task elsewhere – we can’t start an async let
task in one function then pass that task to a different function. On the other hand, if you create a task that returns a string and never throws an error, you can pass that Task<String, Never>
object around as needed.
And finally, although task groups can work with heterogeneous results – i.e., child tasks that return different types of data – it takes the extra work of making an enum to wrap the data. async let
and Task
do not suffer from this problem because they always return a single result type, so each result can be different.
By sheer volume of advantages you might think that async let
is clearly much less useful than both Task
and task groups, but not all those points carry equal weight in real-world code. In practice, I would suggest you’re likely to:
async let
the most; it works best when there is a fixed amount of work to do.Task
for some places where async let
doesn’t work, such as passing an incomplete value to a function.I find that order is pretty accurate in practice, for a number of reasons:
Task
is similar enough to async let
that it’s easy to move across to Task
without going all the way to a task group.So, again I would recommend you start with async let
, move to Task
if needed, then go to task groups only if there’s something specific they offer that you need.
SAVE 50% To celebrate WWDC23, all our books and bundles are half price, so you can take your Swift knowledge further without spending big! Get the Swift Power Pack to build your iOS career faster, get the Swift Platform Pack to builds apps for macOS, watchOS, and beyond, or get the Swift Plus Pack to learn advanced design patterns, testing skills, and more.
Link copied to your pasteboard.