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

如何按顺序执行异步函数?Alamofire调用顺序异常问题

解决异步请求执行顺序问题

问题根源在于first()和second()内部的Alamofire请求是异步操作——调用函数后会立刻返回,请求在后台线程执行,两个请求的完成时间不确定,因此success回调的执行顺序随机。要实现稳定的1 2输出,必须让second()在first()的请求成功后再启动。

下面是几种可行的解决方案:

1. 使用回调闭包(基础兼容方案)

修改first()函数,添加完成回调闭包,在请求成功后触发闭包,再在闭包内调用second():

func first(completion: @escaping () -> Void) {
    // Alamofire 请求逻辑
    AF.request("your_first_api_url").responseJSON { response in
        switch response.result {
        case .success:
            print("1")
            completion() // 成功后触发回调,执行后续逻辑
        case .failure(let error):
            // 可根据业务需求决定是否仍执行后续逻辑
            print(error)
            completion()
        }
    }
}

func second() {
    // Alamofire 请求逻辑
    AF.request("your_second_api_url").responseJSON { response in
        switch response.result {
        case .success:
            print("2")
            self.tableView.reloadData()
        case .failure(let error):
            print(error)
        }
    }
}

@IBAction func click(_ sender: Any) {
    first {
        self.second() // 等待first执行完成后再启动second
    }
}

2. 使用Async/Await(Swift 5.5+ 推荐方案)

如果项目基于Swift 5.5及以上版本,用异步函数替代回调,代码更简洁易读:

func first() async throws {
    // 异步执行Alamofire请求
    _ = try await AF.request("your_first_api_url").serializingData().value
    print("1")
}

func second() async throws {
    // 异步执行Alamofire请求
    _ = try await AF.request("your_second_api_url").serializingData().value
    print("2")
    tableView.reloadData()
}

@IBAction func click(_ sender: Any) {
    Task {
        do {
            try await first()
            try await second() // 按顺序等待first执行完成后再执行second
        } catch {
            print(error)
        }
    }
}

3. 使用Combine框架(适合已集成Combine的项目)

将Alamofire请求转换为Publisher,通过flatMap串联两个请求的执行顺序:

import Combine

func first() -> AnyPublisher<Data, Error> {
    return AF.request("your_first_api_url")
        .serializingData()
        .publishData()
        .tryMap { $0.data }
        .eraseToAnyPublisher()
}

func second() -> AnyPublisher<Data, Error> {
    return AF.request("your_second_api_url")
        .serializingData()
        .publishData()
        .tryMap { $0.data }
        .eraseToAnyPublisher()
}

var cancellables = Set<AnyCancellable>()

@IBAction func click(_ sender: Any) {
    first()
        .handleEvents(receiveOutput: { _ in print("1") })
        .flatMap { _ in self.second() }
        .handleEvents(receiveOutput: { _ in
            print("2")
            self.tableView.reloadData()
        })
        .sink(receiveCompletion: { completion in
            if case .failure(let error) = completion {
                print(error)
            }
        }, receiveValue: { _ in })
        .store(in: &cancellables)
}

所有方案的核心逻辑都是确保第二个请求在第一个请求的成功回调之后才启动,以此保证输出顺序始终为1 2。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 06:15:12