You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 14:52:53