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

RxSwift实现带最大次数限制的网络请求重试方案咨询

解决RxSwift中retry操作符实现网络请求重试的问题

看起来你遇到的核心卡点是:retry操作符默认只在Observable发送error事件时才会触发重试,但你的场景是接口返回success="fail"时需要重试——这属于正常响应结果,不是error,所以原代码没触发重试逻辑。下面我给你一步步拆解解决方案:

第一步:把"fail"响应转换成Error事件

要让retry生效,我们得先把接口返回的success="fail"这种“业务失败”的情况,转换成RxSwift能识别的Error事件。先定义一个自定义错误类型标记这种场景:

enum ApiError: Error {
    case requestFailed
}

// 假设你的接口响应模型是这样的(根据实际情况调整)
struct ApiResponse: Decodable {
    let success: String
}

接着在网络请求的Observable之后,用map操作符判断响应结果:如果success不是"ok",就抛出自定义错误;否则正常返回响应。

第二步:结合retry控制最大重试次数

用retry(_:)操作符设置最大重试次数时要注意:参数是重试的次数,不是总请求次数。比如你要最多重试5次,那总共有1(初始请求) + 5(重试)=6次请求机会;如果希望总请求次数是5次,参数就传4。

下面是完整的可运行代码示例(包含模拟网络请求,方便测试):

import RxSwift
import RxCocoa

let disposeBag = DisposeBag()

// 模拟网络请求(替换成你实际的URLSession请求即可)
func fetchApiData() -> Observable<ApiResponse> {
    // 模拟随机返回ok或fail,方便测试重试逻辑
    let isSuccess = Bool.random()
    let response = ApiResponse(success: isSuccess ? "ok" : "fail")
    return Observable.just(response)
        .delay(.seconds(1), scheduler: ConcurrentDispatchQueueScheduler(qos: .background))
        .observe(on: MainScheduler.instance)
}

// 核心重试逻辑
fetchApiData()
    .map { response -> ApiResponse in
        // 把业务失败转换成Error事件,触发retry机制
        guard response.success == "ok" else {
            throw ApiError.requestFailed
        }
        return response
    }
    .retry(5) // 最多重试5次,总请求次数最多6次
    .subscribe(
        onNext: { _ in
            print("queryedSuccess")
            // 这里处理请求成功后的业务逻辑
        },
        onError: { _ in
            print("queryedFail")
            // 这里处理重试5次后仍失败的业务逻辑
        }
    )
    .disposed(by: disposeBag)

进阶:添加重试间隔(可选)

如果需要在每次重试之间添加延迟(避免频繁请求服务器),可以用retryWhen替代retry,示例如下:

fetchApiData()
    .map { response -> ApiResponse in
        guard response.success == "ok" else {
            throw ApiError.requestFailed
        }
        return response
    }
    .retryWhen { errorObservable -> Observable<Int> in
        errorObservable.enumerated()
            .flatMap { attempt, error -> Observable<Int> in
                // 最多重试5次,超过上限就抛出原错误
                guard attempt < 5 else {
                    return Observable.error(error)
                }
                // 每次重试间隔2秒
                return Observable.timer(.seconds(2), scheduler: MainScheduler.instance).map { _ in attempt }
            }
    }
    .subscribe(
        onNext: { _ in print("queryedSuccess") },
        onError: { _ in print("queryedFail") }
    )
    .disposed(by: disposeBag)

为什么你的原代码只执行一次?

因为你没有把success="fail"转换成Error事件,Observable一直处于正常的Next状态,retry操作符没有触发条件,所以只会执行一次请求。补上“业务失败转Error”的逻辑后,retry就能按预期工作了。

内容的提问来源于stack exchange,提问作者Zigii Wong

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 07:42:40