SWIFT TASK CONTINUATION MISUSE:泄露了它的延续
Posted
技术标签:
【中文标题】SWIFT TASK CONTINUATION MISUSE:泄露了它的延续【英文标题】:SWIFT TASK CONTINUATION MISUSE: leaked its continuation 【发布时间】:2022-01-21 05:54:18 【问题描述】:我正在使用以下函数使用 Alamofire 执行获取请求:
func afRequest(url: URL) async throws -> Data
try await withCheckedThrowingContinuation continuation in
// timeoutInterval is in seconds
AF.request(url, method: .get, requestModifier: $0.timeoutInterval = 10 ).validate(statusCode: 200..<600).responseData response in
if let data = response.data
continuation.resume(returning: data)
return
guard case let .failure(error) = response.result else return
switch error
case .invalidURL(let url):
print("Invalid URL: \(url) - \(error.localizedDescription)")
continuation.resume(throwing: error)
我故意将超时设置为 10 秒来测试这一点。所以错误是"The request timed out."
。之后我收到此错误:
SWIFT TASK CONTINUATION MISUSE: afRequest(url:) leaked its continuation!
我在看this post,但不清楚他们完成了什么或解决方案。缓解这种泄漏的正确方法是什么?
编辑:
这就是我切换上述部分的方式,但还是一样:
if case let .failure(error) = response.result
switch error
case .invalidURL(let url):
...
continuation.resume(throwing: error)
return
编辑 2 - 这是对错误的新处理,但还是一样:
func afRequest(url: URL) async throws -> Data
try await withCheckedThrowingContinuation continuation in
// timeoutInterval is in seconds
AF.request(url, method: .get, requestModifier: $0.timeoutInterval = .infinity ).validate(statusCode: 200..<600).responseData response in
if let data = response.data
continuation.resume(returning: data)
return
if case let .failure(error) = response.result
switch error
case .invalidURL(let url):
print("Invalid URL: \(url) - \(error.localizedDescription)")
// There are more cases...
continuation.resume(throwing: error)
return
else
continuation.resume(throwing: Error.self as! Error)
return
【问题讨论】:
更新到 Alamofire 5.5 以获得内置async
- await
支持。
我已经升级了,但看不出有什么不同,你能发布一个带有错误处理的新异步函数的解决方案吗? @JonShier
您可以阅读文档:github.com/Alamofire/Alamofire/blob/master/Documentation/…
在发帖之前我已经做过了,没有一个清晰完整的例子来说明如何做到这一点@JonShier
文档中有几个例子,我不确定你的意思。 AF.request(...).serializingData()
让您可以像这里一样访问可等待的 API。
【参考方案1】:
你的警卫正在捕获一个案件,而不是要求继续。您需要从所有分支调用延续(例如continuation.resume(...)
),以免泄漏。
这个早期的return
导致了这个问题
guard case let .failure(error) = response.result else return
在您的示例中,您需要决定如何处理 response.data
为零和 response.result
成功,然后更新您的 guard
以适当地调用 continuation.resume(...)
。
【讨论】:
我将其更改为:if case let .failure(error) = response.result
并将 switch 语句放入其中,并在最后继续抛出并返回,但仍然如此:/
从所有分支调用延续是什么意思?
在答案中添加了更多细节
我更改了它,但它说的一样,请参阅上面编辑下我编辑的问题。
这看起来有同样的问题。您需要确保逻辑中的每个分支都调用延续。您所做的更改仅在失败的情况下调用延续。您需要在 if
语句中添加 else
并在其中调用 continuation。以上是关于SWIFT TASK CONTINUATION MISUSE:泄露了它的延续的主要内容,如果未能解决你的问题,请参考以下文章
android kotlin 协程 suspend与continuation