【发布时间】:2020-05-13 18:52:02
【问题描述】:
我正在尝试重新发送针对特定类型错误的请求。假设对于超时错误,我想在延迟 3 秒后重试请求。显然,如果请求成功执行,我不希望有任何延迟。
我正在使用here建议的方法
var cancellables = Set<AnyCancellable>()
let url = URL(string: "https://www.apple.com")!
let sessionConfiguration = URLSessionConfiguration.default
sessionConfiguration.timeoutIntervalForRequest = 1
sessionConfiguration.requestCachePolicy = .reloadIgnoringLocalAndRemoteCacheData
let publisher = URLSession(configuration: sessionConfiguration).dataTaskPublisher(for: url).share()
let head = publisher.print().tryCatch { error -> AnyPublisher<(data: Data, response: URLResponse), URLError> in
switch error {
case URLError.timedOut:
print("I'm in URLError.timedOut case")
return publisher.delay(for: 3, scheduler: DispatchQueue.main).eraseToAnyPublisher()
default:
print("I'm in default case")
throw error
}
}.retry(3)
head.map { data, response in
return data
}.sink(receiveCompletion: {
print("completion \($0)")
}, receiveValue: {
print("value \($0)")
}).store(in: &cancellables)
出于测试目的,我为 URLSession 设置了 1 秒的超时间隔,并限制了我的网络连接,预计当整个管道在大约 10 秒内完成时会看到 4 个失败的请求。但我实际上看到的只是一个失败的请求,并在一段时间后打印了一个失败的完成。对我来说,我似乎每三秒从tryCatch 运营商返回publisher,但由于某种原因,它不会碰巧发送新请求。
我错过了什么?这个问题有其他解决方案吗?
2020 年 14 月 5 日更新
我在tryCatch 之前添加了print() 运算符,并在闭包内添加了一些打印。我在控制台看到的是这个
receive subscription: (Multicast)
request unlimited
receive error: (URLError(_nsError: Error Domain=NSURLErrorDomain Code=-1001 "The request timed out."...))
I'm in URLError.timedOut case
receive subscription: (Multicast)
request unlimited
receive error: (URLError(_nsError: Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." ...))
I'm in URLError.timedOut case
receive subscription: (Multicast)
request unlimited
receive error: (URLError(_nsError: Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." ...))
I'm in URLError.timedOut case
receive subscription: (Multicast)
request unlimited
receive error: (URLError(_nsError: Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." ...))
I'm in URLError.timedOut case
completion failure(Foundation.URLError(_nsError: Error Domain=NSURLErrorDomain Code=-1001 "The request timed out."...))
但我在 Charles http 代理中看到的正是一个请求,即在重试之前发送的一个请求
【问题讨论】:
-
最终打印的完成错误是什么?看起来您在
tryCatch中遇到的错误可能与URLError.timedOut不同。您是否尝试过删除switch并始终返回延迟的发布者(只是看看这是否有效) -
感谢您的提问!我添加了一些打印,可能会有所帮助。对我来说,它看起来非常好,除了从 catch 返回发布者不会触发请求。我也尝试过简单的
catch而不是tryCatch没有任何开关,结果是一样的