Async Composable Architecture: Schedulers

Episode #197 • Jul 18, 2022 • Subscriber-Only

We can now run async work directly in a reducer’s effects, but time-based asynchrony, like Task.sleep, will wreak havoc in our tests. Let’s explore the problem in a new feature, and see how to recover the nice syntax of modern timing tools using a protocol from the past: Combine schedulers.

Timing effects
Async scheduling
Next time: streams

Unlock This Episode

Our Free plan includes 1 subscriber-only episode of your choice, plus weekly updates from our newsletter.


So things are looking pretty good. We are now free to use Swift’s new async/await features directly in the effects returned by reducers. This means we could execute multiple awaits to chain together multiple asynchronous operations, and we could even use async let and task groups to run a multiple units of work in parallel, gathering up their output to feed back into the reducer.

But there are still more types of asynchrony we use in everyday applications, such as time based asynchrony. What do we do if we want to delay for some time in our effects, or throttle or debounce the emissions of effects? Such operations are covered by the Combine framework, and in fact are kinda the whole point of Combine.

However, Swift now has tools that are built on the foundation of async/await that provide a lot of the same functionality that Combine gives us, except in some cases even simpler. Instead of things like the Publisher protocol in Combine for expressing streams of values over time, we now have the AsyncSequence protocol. And instead of things like the Scheduler protocol for expressing how work is scheduled in the future, we now have the Clock protocol. Even better, Apple also has a Swift package called “Async Algorithms” that has all types of interesting operators to use with async sequences, and we will even be able to make use of those in our application.

We’d like to be able to make use of these tools in the library while still maintaining testability. That will be possible, but it will require a bit more time since the tools are still beta and a little buggy as of the most recent Xcode beta (14 beta 3).

So instead, we are going to first introduce new tools to make Combine’s API look more similar to the newer async tools, which will be handy for migrating existing applications to async/await, and then someday in the future we will be able to start using the newer tools, like clocks.

Let’s explore this by adding a new feature to our case study that makes use of time.

This episode is for subscribers only.

Subscribe to Point-Free

Access this episode, plus all past and future episodes when you become a subscriber.

See plans and pricing

Already a subscriber? Log in


Collection: Concurrency

Brandon Williams & Stephen Celis

Swift has many tools for concurrency, including threads, operation queues, dispatch queues, Combine and now first class tools built directly into the language. We start from the beginning to understand what the past tools excelled at and where they faultered in order to see why the new tools are so incredible.