You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在withThrowingTaskGroup中区分处理下载与磁盘存储错误

实现带错误区分的批量图片下载任务组

完全可行,核心思路是在子任务里区分错误类型:下载失败的错误捕获后返回可选值(表示该任务失败但不影响全局),磁盘存储失败的错误直接抛出(触发任务组取消所有任务并向上传递错误)。

具体实现步骤

  1. 定义区分下载/磁盘错误的枚举,让downloadFile能抛出不同类型的错误供后续判断
  2. 修改任务组的输出类型为SampleImage?,允许子任务返回nil(代表下载失败)
  3. 在子任务中捕获下载类错误,返回nil;遇到磁盘类错误直接抛出,触发全局取消
  4. 最终收集结果时过滤掉nil值,只保留成功下载的图片

完整代码示例

首先定义错误枚举:

enum ImageProcessingError: Error {
    case downloadFailed(underlying: Error)
    case diskWriteFailed(underlying: Error)
}

然后修改downloadFile方法,将不同阶段的错误包装成对应的类型:

private func downloadFile(from remoteImage: RemoteImageData) async throws -> SampleImage {
    // 下载阶段
    do {
        let data = try await URLSession.shared.data(from: remoteImage.url).0
        // 磁盘存储阶段
        do {
            let url = try saveDataToDisk(data, filename: remoteImage.filename)
            return SampleImage(localURL: url, originalData: remoteImage)
        } catch {
            throw ImageProcessingError.diskWriteFailed(underlying: error)
        }
    } catch {
        throw ImageProcessingError.downloadFailed(underlying: error)
    }
}

// 辅助存储方法示例
private func saveDataToDisk(_ data: Data, filename: String) throws -> URL {
    let documentsDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
    let fileURL = documentsDir.appendingPathComponent(filename)
    try data.write(to: fileURL)
    return fileURL
}

最后修改批量下载的任务组代码:

private func batchDownloadImages(from remoteImages: [RemoteImageData]) async throws -> [SampleImage] {
    try await withThrowingTaskGroup(of: SampleImage?.self) { group in
        for image in remoteImages {
            group.addTask(priority: .userInitiated) {
                do {
                    return try await self.downloadFile(from: image)
                } catch let error as ImageProcessingError {
                    switch error {
                    case .downloadFailed:
                        // 下载失败,返回nil,不影响其他任务
                        return nil
                    case .diskWriteFailed:
                        // 磁盘存储失败,直接抛出错误,触发任务组取消所有任务
                        throw error
                    }
                } catch {
                    // 其他未知错误,可根据需求选择抛出或返回nil
                    throw error
                }
            }
        }
        
        // 收集结果,过滤掉nil值
        return try await group.reduce(into: [SampleImage]()) { result, image in
            if let image = image {
                result.append(image)
            }
        }
    }
}

关键逻辑说明

  • 当某个子任务抛出diskWriteFailed错误时,withThrowingTaskGroup会立即取消所有未完成的子任务,并且将该错误向上抛出,调用方可以捕获这个错误做后续处理
  • 子任务遇到downloadFailed错误时,返回nil,不会触发任务组的取消逻辑,其他任务会继续执行
  • 最终结果只包含下载且存储成功的图片,下载失败的项会被过滤掉

内容的提问来源于stack exchange,提问作者Bwgan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 04:00:17