我看到如何直接使用.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/

10-12 16:11