Swift并发async/await下如何替代带重试的成功回调模式?
解决方案:封装带重试逻辑的异步请求函数
核心思路是把「请求+失败重试弹窗」的逻辑封装成独立异步函数,调用方无需关心重试细节,只需await函数拿到最终成功结果即可。
实现步骤
1. 封装基础单次请求函数
先实现只负责单次网络请求的抛出型异步函数:
func fetchDataOnce() async throws -> Data { let url = URL(string: "https://your-api-url.com/data")! let (data, response) = try await URLSession.shared.data(from: url) guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { throw NetworkError.invalidResponse } return data } enum NetworkError: Error { case invalidResponse case requestFailed(Error) }
2. 封装带重试交互的请求函数
将请求失败后的弹窗重试逻辑整合进异步循环,通过withCheckedContinuation将UI弹窗的回调转为异步等待:
func fetchDataWithRetry() async throws -> Data { while true { do { return try await fetchDataOnce() } catch { let shouldRetry = await showRetryAlert() if !shouldRetry { throw error // 用户取消重试,抛出原错误 } // 用户选择重试,继续循环发起请求 } } } // 异步弹窗函数,返回用户是否选择重试 func showRetryAlert() async -> Bool { return await withCheckedContinuation { continuation in let alert = UIAlertController(title: "请求失败", message: "是否重试?", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "重试", style: .default) { _ in continuation.resume(returning: true) }) alert.addAction(UIAlertAction(title: "取消", style: .cancel) { _ in continuation.resume(returning: false) }) // 获取当前顶层视图控制器(iOS 13+适配写法) if let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene, let rootVC = scene.windows.first?.rootViewController { rootVC.present(alert, animated: true) } } }
3. 简洁的调用方式
调用方只需await封装后的函数,成功后执行后续操作,失败则处理用户取消的情况:
Task { do { let data = try await fetchDataWithRetry() // 请求成功,执行原回调逻辑(比如显示搜索框) showSearchBar() } catch { print("用户取消请求:\(error)") // 处理用户取消后的逻辑 } }
方案优势
- 完全基于
async/await实现,彻底消除传统完成回调,符合迁移初衷。 - 循环+异步等待的逻辑保证:首次失败后,用户点击重试会重新发起请求,直到成功或用户取消,最终成功时能正常触发后续操作。
- 请求逻辑与UI交互逻辑解耦,代码结构更清晰,便于维护和扩展。
注意事项
- 可根据错误类型调整重试策略,比如仅对网络超时、服务器错误等可重试错误弹窗,在
catch分支中判断错误类型即可。 - 顶层视图控制器的获取方式需根据项目的UI架构调整,确保弹窗能正确显示。
内容的提问来源于stack exchange,提问作者matt
相关产品推荐
相关产品推荐

