如何将非典型完成处理程序转换为Swift Concurrency语法?
Swift Concurrency 转换:处理同时返回值和错误的场景
原来基于完成回调的异步方法里,你遇到了「缓存过期但网络不可用时,同时返回缓存值和CacheError.outdatedCache错误」的场景,但Swift Concurrency的async throws模式本身是二选一的逻辑:要么成功返回值,要么抛出错误,没法同时传递两者。所以不能直接套用常规的withCheckedThrowingContinuation写法,得通过调整返回类型来解决。
下面是两种可行的方案:
方案一:自定义结果结构体承载值和可选错误
直接定义一个结构体,把数据和可能的缓存错误打包在一起返回,不需要使用throws:
// 先定义你的缓存错误类型 enum CacheError: Error { case outdatedCache // 其他缓存相关错误... } // 自定义结果结构体 struct CacheResult<T> { let data: T let cacheError: CacheError? } // 转换后的异步方法 func fetchData() async -> CacheResult<Data> { return await withCheckedContinuation { continuation in // 调用原来的基于完成回调的方法 legacyFetchData { data, error in // 这里假设data非空(你的场景下缓存过期时也有值) let result = CacheResult( data: data!, cacheError: error as? CacheError ) continuation.resume(returning: result) } } }
调用时可以同时获取数据和缓存状态:
let result = await fetchData() // 使用拿到的数据 processData(result.data) // 处理缓存过期的提示 if result.cacheError == .outdatedCache { showExpiredCacheWarning() }
方案二:用枚举明确区分不同状态
如果想更清晰地表达「正常成功」「过期缓存」「完全失败」这几种场景,可以用枚举来封装结果:
enum FetchResult<T> { case success(T) // 正常拿到最新数据 case outdatedCache(T) // 缓存过期,但返回缓存数据 case failure(Error) // 完全获取失败,无数据 } // 转换后的异步方法 func fetchData() async -> FetchResult<Data> { return await withCheckedContinuation { continuation in legacyFetchData { data, error in if let data = data { if let cacheError = error as? CacheError, cacheError == .outdatedCache { continuation.resume(returning: .outdatedCache(data)) } else { continuation.resume(returning: .success(data)) } } else if let error = error { continuation.resume(returning: .failure(error)) } else { // 处理极端情况:data和error都为空 continuation.resume(returning: .failure(CacheError.unknown)) } } } }
调用时通过switch分支处理不同状态:
switch await fetchData() { case .success(let data): processData(data) hideExpiredWarning() case .outdatedCache(let data): processData(data) showExpiredCacheWarning() case .failure(let error): showFetchFailureAlert(error) }
关键说明
之所以不能用async throws直接处理,是因为throws的语义是「操作失败,无法返回有效结果」,但你的场景是「操作虽然有警告(缓存过期),但仍有可用结果」,这不符合throws的设计意图。所以必须通过自定义返回类型,把「结果数据」和「状态/警告」打包在一起传递。
内容的提问来源于stack exchange,提问作者KPM
相关产品推荐
相关产品推荐

