Swift并发:catch块重抛方法及async/await递归请求重试问题
Swift并发重试逻辑、catch重抛与递归处理
一、解决当前重试代码的错误问题
你遇到的Errors thrown from here are not handled错误,原因是Task.sleep(nanoseconds:)是抛出型方法(会抛出CancellationError),且你在catch块中直接调用但未处理它的错误。同时注意Task.sleep的参数是纳秒,5秒需要传入5_000_000_000而非5。
修正后的重试代码:
func checkVersion() async { do { let versionEntity = try await getVersionAsync() // 处理版本实体逻辑 print("版本获取成功: \(versionEntity)") } catch { do { // 等待5秒(转换为纳秒) try await Task.sleep(nanoseconds: 5_000_000_000) await checkVersion() } catch is CancellationError { // 任务被取消时终止重试 print("版本检查任务已取消") } catch { // 处理等待过程中的其他异常,继续重试 print("等待重试出错: \(error)") await checkVersion() } } }
二、Swift并发中catch块的重抛方法
若需要在catch块中重抛错误,需确保当前函数标记为async throws,然后直接使用throw error即可。也可根据错误类型选择性重抛:
1. 直接重抛全部错误
func checkVersion() async throws { do { let versionEntity = try await getVersionAsync() // 处理版本实体 } catch { // 先执行日志等前置操作,再重抛 print("版本获取失败: \(error.localizedDescription)") throw error } }
2. 选择性重抛特定错误
enum APIError: Error { case networkFailure case invalidResponse } func checkVersion() async throws { do { let versionEntity = try await getVersionAsync() // 处理版本实体 } catch let apiError as APIError { print("API错误: \(apiError)") throw apiError // 仅重抛API相关错误 } catch { print("非API错误,内部处理: \(error)") // 不重抛,内部消化该错误 } }
三、async/await递归的相关处理
异步递归虽不会像同步递归那样快速导致栈溢出(因异步函数挂起时会释放栈资源),但仍需注意以下几点:
1. 设置重试次数上限
避免无限递归消耗资源,通过参数控制最大重试次数:
func checkVersion(maxRetries: Int = 3) async { do { let versionEntity = try await getVersionAsync() // 处理版本实体 print("版本获取成功: \(versionEntity)") } catch { guard maxRetries > 0 else { print("重试次数耗尽,版本获取失败: \(error)") return } do { try await Task.sleep(nanoseconds: 5_000_000_000) await checkVersion(maxRetries: maxRetries - 1) } catch is CancellationError { print("任务取消,终止重试") } catch { print("等待重试出错,剩余重试次数: \(maxRetries - 1)") await checkVersion(maxRetries: maxRetries - 1) } } }
2. 根据错误类型决定是否重试
仅对可恢复错误(如网络波动)进行重试,业务错误直接终止:
func checkVersion(maxRetries: Int = 3) async { do { let versionEntity = try await getVersionAsync() // 处理版本实体 } catch let error as APIError where error == .networkFailure { // 仅网络错误重试 guard maxRetries > 0 else { print("网络错误重试耗尽: \(error)") return } try await Task.sleep(nanoseconds: 5_000_000_000) await checkVersion(maxRetries: maxRetries - 1) } catch { print("无需重试的错误: \(error)") } }
3. 响应任务取消
当异步任务被取消时,Task.sleep会抛出CancellationError,需捕获该错误并终止递归,避免无效重试。
内容的提问来源于stack exchange,提问作者Nike Kov
相关产品推荐
相关产品推荐

