如何将Alamofire完成回调转换为Swift 5.5的Async/Await异步实现
Swift 回调式函数转换为async/await实现方案
原有尝试写法的问题
你写的getTokenBalances3没有输出的核心原因有2个:
- 你封装的
Task内部没有定义返回值,最终拿到的result1是Void类型,print自然没有内容 - JSON解析是同步操作,不需要额外封装Task执行,直接在当前异步上下文运行即可
- 强制解包
URL和response.data存在崩溃风险,没有兼容错误场景
标准改造实现(完全对齐原有回调函数逻辑)
原来的回调函数返回布尔值标识是否成功,对应改造后的代码如下:
func getTokenBalances() async -> Bool { guard let url = URL(string: "someApiUrlFromLostandFound") else { print("Invalid URL") return false } // 通过withCheckedContinuation桥接回调和async上下文 return await withCheckedContinuation { continuation in AF.request(url, method: .get).validate().responseData { response in do { guard let data = response.data else { print("Response Error:", response.error as Any) // 回调返回false对应continuation返回false continuation.resume(returning: false) return } let apiJsonData = try JSONDecoder().decode(TokenBalanceClassAModel.self, from: data) DispatchQueue.main.async { self.getTokenBalancesModel = apiJsonData.data.items // 成功场景返回true continuation.resume(returning: true) } } catch { print("ERROR:", error) continuation.resume(returning: false) } } } }
调用的时候直接用let success = await getTokenBalances()即可拿到执行结果。
更推荐的抛错版实现
如果不需要兼容原有布尔返回值的逻辑,更建议用CheckedThrowingContinuation把错误向上抛出,调用侧可以灵活处理不同异常场景:
// 自定义错误类型 enum TokenBalanceError: Error { case invalidUrl case responseError(Error?) case decodeError(Error) } func getTokenBalances() async throws -> [TokenBalanceItem] { // 替换为你items的实际类型 guard let url = URL(string: "someApiUrlFromLostandFound") else { throw TokenBalanceError.invalidUrl } return try await withCheckedThrowingContinuation { continuation in AF.request(url, method: .get).validate().responseData { response in switch response.result { case .success(let data): do { let apiJsonData = try JSONDecoder().decode(TokenBalanceClassAModel.self, from: data) let items = apiJsonData.data.items DispatchQueue.main.async { self.getTokenBalancesModel = items continuation.resume(returning: items) } } catch { continuation.resume(throwing: TokenBalanceError.decodeError(error)) } case .failure(let error): continuation.resume(throwing: TokenBalanceError.responseError(error)) } } } }
调用时用do-catch捕获错误即可:
do { let balances = try await getTokenBalances() print(balances) } catch { print("请求失败:", error) }
你自行实现的getSupportedChains优化建议
你自己写的版本已经可以正常运行,只需修改2点即可更安全:
- 不要强制解包
URL和apiRequest.data,增加校验逻辑 - 可以替换为
withCheckedThrowingContinuation把错误抛出,避免内部吞掉错误
内容的提问来源于stack exchange,提问作者Arturo
相关产品推荐
相关产品推荐

