Async Composable Architecture: Effect Lifetimes

Episode #199 • Aug 1, 2022 • Subscriber-Only

We explore ways to tie the lifetime of an effect to the lifetime of a view, making it possible to automatically cancel and tear down work when a view goes away. This unexpectedly helps us write even stronger tests for our features.

Previous episode
Async Composable Architecture: Effect Lifetimes
Next episode
Locked

Unlock This Episode

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

Sign in with GitHub

Introduction

It’s a bit of a bummer that we need to insert this yield. We don’t even know if it’s enough to get things to always pass. Maybe if we run this enough times it will eventually fail, leading us to insert a few additional yields to push things along.

One thing that could potentially fix this is if Swift supported async deinit for objects, because then we could suspend for a bit when the test store is torn down to see if all effects finished, and if not then we could error. There has been some discussions of this in the evolution forums, but no movement on a final design yet.

But, even before we get that feature, there’s still something we can do to make this work deterministically without sprinkling yields into the test. It is possible to send an action to the store and get back a task that represents the lifecycle of the effect that was kicked off from that action. That would give you something concrete to await on so that you could suspend until the exact moment that the effect finishes. This would give us a 100% deterministic way to make our test pass.

It also turns out that by getting a handle on an effect’s lifecycle we can improve other parts of the library too. For example, SwiftUI has an interesting view modifier called .task that allows you to spin up some asynchronous work when the view appears, and that work is automatically cancelled when the view disappears.

Wouldn’t it be cool if we could send an action in that task modifier so that when the view disappears it cancels the inflight effect that was kicked off from the action? This makes it possible for a feature to seamlessly tear down its effects when the view disappears.

Let’s see how this is possible.

The problem


References

  • Collection: Concurrency
    Brandon Williams & Stephen Celis
    Note

    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.

Downloads

Get started with our free plan

Our free plan includes 1 subscriber-only episode of your choice, access to 64 free episodes with transcripts and code samples, and weekly updates from our newsletter.

View plans and pricing