Last active
January 11, 2026 19:35
-
-
Save robertmryan/a186546becfdca50ce45eaf3098e441d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // The three child functions can presumably fail for a variety of reasons: | |
| // | |
| // 1. The request of data from the cloud failed. | |
| // 2. The saving of the data locally failed. | |
| // 3. The function was canceled. | |
| // | |
| // And for each of these, you want to let the parent task know why it failed. | |
| // So, we would generally mark these child functions as `throws`. | |
| // | |
| // And we would explicitly avoid ever using `try?` or `try!` in these child | |
| // functions. And we’d avoid a `catch` block (to allow errors to percolate up | |
| // to the caller that will update the UI), or if the child function did need | |
| // a `catch` block, we’d also have that block re-`throw` the error. | |
| // | |
| // We would also avoid introducing any unnecessary unstructured | |
| // concurrency (e.g., `Task {…}` or `Task.detached {…}`) in these child | |
| // functions. As an aside, in the unlikely case that unstructured concurrency, | |
| // was needed, we would wrap that in a `withTaskCancellationHandler`, but that | |
| // is beyond the scope of the question. | |
| func updateDrumsFromTheCloud() async throws {…} | |
| func updateMixFromTheCloud() async throws {…} | |
| func updateClapsFromTheCloud() async throws {…} | |
| // Anyway, we can then just `try await` these calls, with no explicit | |
| // `Task.isCancelled` checks: | |
| func updateEverythingFromTheCloud() async throws { | |
| try await updateDrumsFromTheCloud() // these take a minute | |
| try await updateMixFromTheCloud() | |
| try await updateClapsFromTheCloud() | |
| } | |
| // And then the caller might, for example, create the `Task` for this async | |
| // work, and then update the UI accordingly: | |
| var updateTask: Task<Void, Never>? | |
| updateTask = Task { | |
| do { | |
| try await updateEverythingFromTheCloud() | |
| await refreshUI() | |
| } catch { | |
| await updateUI(for: error) | |
| } | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
By the way, if you want advice on how to make these three child functions handle cancellation properly, maybe you can share an example implementation of be of them, and we can advise further.