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

Alamofire使用串行队列配置后请求乱序,如何维持请求与结果FIFO顺序?

问题根因

你配置的串行队列仅作用于Alamofire内部的任务调度逻辑,不会限制网络请求本身的执行与返回顺序:

  • 你开启了 startRequestsImmediately = true,请求创建完成后会直接提交到底层URLSession执行,而URLSession默认会并发处理所有请求,不同请求的网络响应时间受接口响应速度、网络波动影响天然不固定,自然会出现后创建的请求先返回的情况
  • 串行序列化队列仅保证序列化任务按入队顺序执行,但如果网络响应返回顺序本身是乱序的,序列化任务的入队顺序自然也是乱的,最终输出顺序就不符合预期
实现请求与结果FIFO的两种方案

方案1:请求串行执行(上一个请求完成后再发起下一个)

适合请求之间存在强依赖、必须按顺序执行的场景,实现逻辑简单:

  1. 首先修改Session配置,关闭自动启动请求:
let queue = DispatchQueue(label: "APIManager.rootQueue")
a.session = Session(configuration: sessionConfiguration,
                    delegate: a,
                    rootQueue: queue,
                    startRequestsImmediately: false, // 关闭自动启动
                    requestQueue: queue,
                    serializationQueue: queue,
                    interceptor: nil,
                    serverTrustManager: nil,
                    redirectHandler: nil,
                    cachedResponseHandler: nil,
                    eventMonitors: [])
  1. 维护请求等待队列,按顺序触发请求执行:
// 全局维护请求队列与执行状态
private var pendingRequests: [Request] = []
private var isRunningRequest = false

// 对外暴露的请求入队方法
func addRequestToQueue(_ request: Request) {
    pendingRequests.append(request)
    runNextRequestIfPossible()
}

private func runNextRequestIfPossible() {
    guard !isRunningRequest, !pendingRequests.isEmpty else { return }
    isRunningRequest = true
    let currentRequest = pendingRequests.removeFirst()
    // 监听请求完成回调
    currentRequest.response(queue: queue) { [weak self] response in
        guard let self = self else { return }
        // 此处处理你的响应、序列化逻辑
        // 执行完成后触发下一个请求
        self.isRunningRequest = false
        self.runNextRequestIfPossible()
    }
    currentRequest.resume()
}

方案2:请求并发执行,结果按创建顺序回调

适合需要并发请求提升效率、但要求回调顺序和创建顺序一致的场景,性能更高:

// 全局维护结果缓存、当前待回调的序号、请求创建序号
private var resultCache: [Int: Any] = [:]
private var nextCallbackIndex = 0
private var requestSequence = 0

// 对外暴露的请求方法
func sendRequestWithOrderedCallback(_ request: Request, callback: @escaping (Any) -> Void) {
    let currentIndex = requestSequence
    requestSequence += 1
    // 监听请求响应
    request.response(queue: queue) { [weak self] response in
        guard let self = self else { return }
        // 先把结果存入缓存
        self.resultCache[currentIndex] = response
        // 按顺序触发所有已返回的请求回调
        while let readyResult = self.resultCache[self.nextCallbackIndex] {
            callback(readyResult)
            self.resultCache.removeValue(forKey: self.nextCallbackIndex)
            self.nextCallbackIndex += 1
        }
    }
    request.resume()
}
注意事项
  • 方案1会牺牲请求并发性能,仅适合请求间有强依赖的场景
  • 方案2需要注意内存占用,如果出现大量请求长时间未返回的情况,缓存的结果会持续占用内存,可根据业务需求添加超时清理逻辑

内容的提问来源于stack exchange,提问作者Peter Lapisu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 04:15:03