MiddleCodeCommonNot answered yet
Bridge a completion-handler API to async with a checked continuation
A legacy API loads a user through a completion handler. Wrap it in an async throws function using a checked continuation.
Requirements:
- Return the
Useron success, throw the error on failure. - Resume the continuation exactly once on every path.
func legacyLoadUser(id: Int, completion: @escaping (Result<User, Error>) -> Void) { /* given */ }
func loadUser(id: Int) async throws -> User {
// your code here
}
Write the implementation.
withCheckedThrowingContinuation gives a continuation; resume it exactly once — returning or throwing. Resuming twice traps, since it crashes on the second call; never resuming hangs the task forever at await.
- ✗Thinking a continuation may be resumed more than once
- ✗Assuming a forgotten
resumeis cleaned up instead of hanging - ✗Confusing checked (traps) with unsafe (undefined) continuations
- →What does the checked variant of
withCheckedContinuationverify at runtime? - →How would you guard a continuation that a callback might invoke twice?
resume(with:) maps a Result to the right resume(returning:) / resume(throwing:), and the Result callback fires once, so the continuation resumes exactly once:
func loadUser(id: Int) async throws -> User {
try await withCheckedThrowingContinuation { continuation in
legacyLoadUser(id: id) { result in
continuation.resume(with: result) // exactly once: success or failure
}
}
}
If the API could call back twice, the second resume would trap; if it could skip the callback, the await would hang forever. So the wrapped API must guarantee exactly one call.