延迟后是否合并框架重试? [英] Combine framework retry after delay?

查看:61
本文介绍了延迟后是否合并框架重试?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看到如何直接使用 .retry 来在出现错误后重新订阅,如下所示:

I see how to use .retry directly, to resubscribe after an error, like this:

    URLSession.shared.dataTaskPublisher(for:url)
        .retry(3)

但是,这似乎很简单.如果我认为如果我稍等一下,该错误可能会消失怎么办?我可以插入 .delay 运算符,但是即使没有错误,延迟也会起作用.而且似乎没有办法有条件地应用运算符(即仅在出现错误时).

But that seems awfully simple-minded. What if I think that this error might go away if I wait awhile? I could insert a .delay operator, but then the delay operates even if there is no error. And there doesn't seem to be a way to apply an operator conditionally (i.e. only when there's an error).

我了解了如何通过从头开始编写RetryWithDelay运算符来解决此问题,实际上,这种运算符已由第三方编写.但是,有一种方法可以纯粹使用我们得到的运算符说如果有错误则延迟"吗?

I see how I could work around this by writing a RetryWithDelay operator from scratch, and indeed such an operator has been written by third parties. But is there a way to say "delay if there's an error", purely using the operators we're given?

我的想法是我可以使用 .catch ,因为它的功能仅在出现错误时运行.但是该函数需要返回一个发布者,我们将使用哪个发布者?如果我们返回 somePublisher.delay(...)后跟 .retry ,则将 .retry 应用于错误的发布者,不是吗?

My thought was that I could use .catch, because its function runs only if there is an error. But the function needs to return a publisher, and what publisher would we use? If we return somePublisher.delay(...) followed by .retry, we'd be applying .retry to the wrong publisher, wouldn't we?

推荐答案

这是使用组合项目回购了一段时间-整个线程: https://github.com/heckj/swiftui-notes/issues/164 .

It was a topic of conversation on the Using Combine project repo a while back - the whole thread: https://github.com/heckj/swiftui-notes/issues/164.

总之,我们做了一个例子,尽管它确实使用了 catch :

The long and short was we made an example that I think does what you want, although it does use 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()
}

这是指我在书/在线版本中使用的重试模式,这基本上就是您所描述的(但不是您所询问的).

This is referencing the a retry pattern I have in the book/online, which is basically what you describe (but wasn't what you asked about).

我在此问题上与之对应的在该线程中提供了一个变体作为扩展,可能很有趣以及:

The person I was corresponding with on the issue provided a variant in that thread as an extension that might be interesting as well:

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()
    }
  }
}

这篇关于延迟后是否合并框架重试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆