如何按顺序执行异步函数?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
相关产品推荐
相关产品推荐

