如何在批量异步requestItem请求全部完成后执行后续代码?
如何等待所有异步请求完成后执行后续代码?
首先得纠正一个小问题:你原来的代码里let item = requestItem(id)写法不对哦——异步函数不会直接返回结果,通常是通过闭包回调或者async/await来传递结果的,直接赋值拿不到正确的异步返回值。
下面给你两种常用的解决方案,适配不同的Swift版本:
方案一:用DispatchGroup(兼容Swift 5.5之前的版本)
DispatchGroup是苹果提供的用来跟踪一组异步任务的工具,每个任务开始时“进入”group,完成时“离开”group,当所有任务都离开后,就能触发后续逻辑。
假设你的requestItem是基于闭包的异步函数(比如定义为:func requestItem(_ id: Int, completion: @escaping (Item?) -> Void)),代码可以这么写:
var IDs = [Int]() var items = [Item]() let taskGroup = DispatchGroup() // 可选:如果需要保证items数组的线程安全,用一个串行队列 let itemsQueue = DispatchQueue(label: "com.yourapp.itemsQueue") for id in IDs { taskGroup.enter() // 标记一个任务开始 requestItem(id) { [weak self] fetchedItem in defer { taskGroup.leave() } // 无论成功失败,都要离开group,避免死等 guard let item = fetchedItem else { print("加载id:\(id)失败") return } // 线程安全地更新items数组 itemsQueue.sync { self?.items.append(item) } } } // 所有任务完成后执行后续代码 taskGroup.notify(queue: .main) { [weak self] in print("所有Item都加载完成啦!当前items数量:\(self?.items.count ?? 0)") // 这里写你的后续逻辑,比如更新UI、处理数据等 }
注意点:
- 一定要保证每个
enter()对应一个leave(),哪怕请求失败也要调用,不然group会一直等待,后续代码永远不会执行。 - 如果异步回调在后台线程,更新
items时要注意线程安全,用串行队列或者锁来避免数据竞争。
方案二:用async/await(Swift 5.5+,iOS 15+/macOS 12+等)
这是Swift现代并发模型推荐的方式,代码更简洁易读,错误处理也更规范。
首先需要你的requestItem是异步函数(比如定义为:func requestItem(_ id: Int) async throws -> Item),然后可以用Task来并发执行所有请求,再等待全部完成:
var IDs = [Int]() // 封装加载逻辑的异步函数 func loadAllItems() async -> [Item] { // 创建一组并发任务 let tasks = IDs.map { id in Task { do { return try await requestItem(id) } catch { print("加载id:\(id)失败:\(error)") throw error // 也可以返回nil,根据你的需求调整错误处理逻辑 } } } // 等待所有任务完成,收集结果 var items = [Item]() for task in tasks { do { let item = try await task.value items.append(item) } catch { // 单个任务失败的处理,比如跳过该item continue } } return items } // 调用方式(必须在异步上下文里,比如Task中) Task { let allLoadedItems = await loadAllItems() print("所有Item加载完成,共\(allLoadedItems.count)个") // 这里执行后续代码,比如更新UI(如果在主队列的Task,直接操作UI即可) // self.items = allLoadedItems }
优势:
- 代码结构更线性,不用嵌套多层闭包,可读性更强。
- 错误处理通过
do-catch统一管理,逻辑更清晰。 - 系统自动处理线程调度,不用手动管理队列和线程安全(只要不在多个Task里同时修改同一个可变变量即可)。
内容的提问来源于stack exchange,提问作者moonvader
相关产品推荐
相关产品推荐

