我看到如何直接使用.retry
,在出现错误后重新订阅,如下所示:
URLSession.shared.dataTaskPublisher(for:url)
.retry(3)
但这似乎很简单。如果我认为如果我稍等一下,该错误可能会消失怎么办?我可以插入
.delay
运算符,但是即使没有错误,延迟也会起作用。而且似乎没有办法有条件地应用运算符(即仅在出现错误时)。我看到了如何通过从头开始编写RetryWithDelay运算符来解决此问题,的确,这种运算符已由第三方编写。但是,有一种方法可以纯粹使用我们得到的运算符说“如果有错误则延迟”吗?
我的想法是我可以使用
.catch
,因为它的功能仅在出现错误时运行。但是该函数需要返回一个发布者,我们将使用哪个发布者?如果我们返回somePublisher.delay(...)
后跟.retry
,我们将.retry
应用于错误的发布者,不是吗? 最佳答案
前一阵子是Using Combine项目 repo 中的一个讨论话题-整个线程:https://github.com/heckj/swiftui-notes/issues/164。
总而言之,尽管我们确实使用了catch
,但我们还是做了一个我想做的例子:
let resultPublisher = upstreamPublisher.catch { error -> AnyPublisher<String, Error> in
return Publishers.Delay(upstream: upstreamPublisher,
interval: 3,
tolerance: 1,
scheduler: DispatchQueue.global())
// moving retry into this block reduces the number of duplicate requests
// In effect, there's the original request, and the `retry(2)` here will operate
// two additional retries on the otherwise one-shot publisher that is initiated with
// the `Publishers.Delay()` just above. Just starting this publisher with delay makes
// an additional request, so the total number of requests ends up being 4 (assuming all
// fail). However, no delay is introduced in this sequence if the original request
// is successful.
.retry(2)
.eraseToAnyPublisher()
}
这引用的是retry pattern I have in the book/online,基本上是您所描述的(但不是您所要的)。
person I was corresponding with on the issue在该线程中提供了一个变体作为扩展,可能也很有趣:
extension Publisher {
func retryWithDelay<T, E>()
-> Publishers.Catch<Self, AnyPublisher<T, E>> where T == Self.Output, E == Self.Failure
{
return self.catch { error -> AnyPublisher<T, E> in
return Publishers.Delay(
upstream: self,
interval: 3,
tolerance: 1,
scheduler: DispatchQueue.global()).retry(2).eraseToAnyPublisher()
}
}
}
关于ios - 延迟后是否合并框架重试?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/60624851/