如何将含递归的Completion Handler函数转换为Async函数?
将基于Completion的递归函数转换为Async/Await函数
问题背景
原来的函数通过completion回调实现递归数据获取:
func myFunction(currentList: [String] = [], startIndex: Int = 0, completion: @escaping ([String]) -> Void) { var list = currentList let maxSize = 10 let endIndex = startIndex + maxSize - 1 privateFunction(range: startIndex...endIndex) { items in list.append(contentsOf: items) if items.count < maxSize { completion(list) } else { myFunction(currentList: list, startIndex: startIndex + maxSize, completion: completion) } } }
需要将其转换为支持async/await的版本,已尝试用withCheckedContinuation改造,但递归分支的实现存疑。
解决方案
核心思路是在递归分支中,通过Task异步调用新版的async函数,拿到最终递归结果后再resume continuation:
func myFunction(currentList: [String] = [], startIndex: Int = 0) async -> [String] { var list = currentList let maxSize = 10 let endIndex = startIndex + maxSize - 1 return await withCheckedContinuation { continuation in privateFunction(range: startIndex...endIndex) { items in list.append(contentsOf: items) if items.count < maxSize { // 数据已取完,直接返回结果 continuation.resume(returning: list) } else { // 递归调用async版本,拿到最终结果后resume Task { let finalList = await myFunction(currentList: list, startIndex: startIndex + maxSize) continuation.resume(returning: finalList) } } } } }
关键细节说明
修正笔误与逻辑错误:
- 原代码中
start应为startIndex,否则会出现未定义变量错误 - 原代码用
list.append(items)会将整个items数组作为单个元素添加,需改为append(contentsOf: items)才能正确合并数组
- 原代码中
递归分支处理:
由于privateFunction的回调是同步上下文,无法直接在其中使用await,因此通过Task开启异步任务执行递归调用,待递归完成拿到最终结果后,再调用continuation.resume(returning:)传递结果,确保withCheckedContinuation仅被resume一次,符合其使用规范。
内容的提问来源于stack exchange,提问作者Swiftylicious2
相关产品推荐
相关产品推荐

