将带Completion的第三方库方法转为Async/Await的正确性及优势探讨
针对第三方回调API的async/await改写分析
一、你的改写是否正确?
整体思路是对的——用withCheckedContinuation把基于Completion回调的异步方法包装成async/await形式,这是Swift里适配旧回调API的标准操作。但当前实现有个关键优化点:
你只调用了continuation.resume()让函数恢复执行,却没有把登录的结果(成功的authState或失败的error)传递给调用方。现在的写法里,调用login()的代码没法直接感知登录状态,只能靠内部的setAuthState和日志判断,这不符合async/await模式下“结果可被调用方直接获取”的设计逻辑。
更规范的写法应该把结果通过continuation传递出去,比如返回OIDAuthState并抛出错误:
func login() async throws -> OIDAuthState { // 配置client ID、redirect URI等逻辑省略 return try await withCheckedThrowingContinuation { continuation in self.appDelegate.currentAuthorizationFlow = OIDAuthState.authState(byPresenting: request, presenting: scene!.keyWindow!.rootViewController!) { authState, error in if let authState = authState { self.setAuthState(authState) print("Got authorization tokens!") self.retrieveCookies() continuation.resume(returning: authState) } else { let loginError = error ?? NSError(domain: "LoginError", code: -1, userInfo: [NSLocalizedDescriptionKey: "Unknown authorization error"]) print("Authorization error: \(loginError.localizedDescription)") self.setAuthState(nil) continuation.resume(throwing: loginError) } } } }
这样调用方可以用do-catch捕获错误,同时直接拿到成功的authState,完全贴合async/await的使用习惯。
二、async/await相比原回调写法的优势
- 代码更易读易维护:告别嵌套闭包的“回调地狱”,异步逻辑按顺序线性书写,和同步代码结构一致,一眼就能理清流程,后期改bug、加功能都更省力。
- 错误处理更统一:用Swift标准的
do-catch语法集中处理错误,替代回调里零散的if let error判断,错误逻辑更清晰,不容易漏处理。 - 完美适配Actor模型:这也是你提到的核心需求——Actor是Swift并发模型的核心,async/await和Actor天然兼容,在Actor里调用async方法会自动处理线程调度,从根源上避免数据竞争,符合现代Swift并发的规范。
- 异步任务取消更便捷:基于async/await的任务可以用
Task.cancel()一键取消,而回调模式下需要手动维护currentAuthorizationFlow并调用取消方法,代码冗余且容易出错。 - 异步操作组合更灵活:如果后续要串联多个异步步骤(比如登录后调用用户信息接口),async/await直接用
await按顺序调用就行,回调模式则要嵌套多层,代码复杂度会直线上升。
内容的提问来源于stack exchange,提问作者Pieter
相关产品推荐
相关产品推荐

