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

Swift中如何取消URLSession异步函数对应的URLSessionTask?

取消URLSession异步await任务的两种方法

使用URLSession的异步await API时,确实没有直接暴露底层的URLSessionTask供调用cancel(),但有两种实用方式实现任务完成前的取消:

1. 自定义封装API,直接获取并控制底层Task

如果需要主动拿到URLSessionDataTask实例来随时取消,可以用withCheckedThrowingContinuation封装一个带取消能力的异步方法,把底层Task暴露出来:

extension URLSession {
    func cancellableDataTask(with request: URLRequest) -> (task: URLSessionDataTask, fetch: () async throws -> (Data, URLResponse)) {
        var task: URLSessionDataTask!
        let fetch = { try await withCheckedThrowingContinuation { continuation in
            task = self.dataTask(with: request) { data, response, error in
                if let error = error {
                    continuation.resume(throwing: error)
                    return
                }
                guard let data = data, let response = response else {
                    continuation.resume(throwing: URLError(.badServerResponse))
                    return
                }
                continuation.resume(returning: (data, response))
            }
            task.resume() // 启动任务
        }}
        return (task, fetch)
    }
}

使用示例:

guard let url = URL(string: "https://example.com") else { return }
let request = URLRequest(url: url)
let (task, fetchData) = URLSession.shared.cancellableDataTask(with: request)

// 随时调用取消
task.cancel()

// 等待任务结果
do {
    let (data, response) = try await fetchData()
    // 处理响应数据
} catch {
    if (error as NSError).code == URLError.cancelled.rawValue {
        print("任务已取消")
    } else {
        print("请求错误:\(error)")
    }
}

2. 利用Swift Task的取消机制(系统版本要求iOS 15+/macOS 12+)

在iOS 15及以上、macOS 12及以上的系统中,URLSession的异步API已和Swift的Task取消机制深度集成。取消包裹异步请求的Task,底层的URLSessionTask会自动被终止:

guard let url = URL(string: "https://example.com") else { return }
let requestTask = Task {
    do {
        let (data, response) = try await URLSession.shared.data(from: url)
        // 处理数据
    } catch is CancellationError {
        print("Swift Task被取消,底层URLSessionTask也已终止")
    } catch {
        print("请求异常:\(error)")
    }
}

// 取消外层Task,触发底层请求取消
requestTask.cancel()

这种方式无需额外封装,适合不需要直接操作底层Task的场景,代码更简洁。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 12:10:03