簡體   English   中英

如何在 ios 應用程序中重試失敗的 Web 服務調用延遲時間

[英]How to retry failed web service calls with time delay in ios app

我正在開發一個 IOS 應用程序,根據要求,我需要重試所有失敗的 api 3 次,延遲 3 秒。 為了做到這一點,我向發布者添加了一個擴展,如下所示,但是這段代碼有一個小問題,在最后一次嘗試之后,如果我得到一個失敗的響應,那么執行預期的失敗代碼需要 3 秒。 我需要在上次嘗試失敗后立即顯示失敗消息,有什么辦法可以解決這個問題嗎?

public extension Publisher {
    func retryWithDelay<S>(
        retries: Int,
        delay: S.SchedulerTimeType.Stride,
        scheduler: S
    ) -> AnyPublisher<Output, Failure> where S: Scheduler {
        
        self
            .delayIfFailure(for: delay, scheduler: scheduler)
            .retry(retries)
            .eraseToAnyPublisher()
    }

    private func delayIfFailure<S>(
        for delay: S.SchedulerTimeType.Stride,
        scheduler: S
    ) -> AnyPublisher<Output, Failure> where S: Scheduler {
        self.catch { error in
            Future { completion in
                scheduler.schedule(after: scheduler.now.advanced(by: delay)) {
                    completion(.failure(error))
                }
            }
        }
        .eraseToAnyPublisher()
    }
}

最好創建一個自定義Publisher ,其想法是您將跟蹤失敗的次數,並在正常情況下返回延遲發布者(失敗),或最后一個非延遲發布者重試。

struct RetryWithDelay<Upstream: Publisher, S: Scheduler>: Publisher {
    
   typealias Output = Upstream.Output
   typealias Failure = Upstream.Failure
    
   let upstream: Upstream
   let retries: Int
   let interval: S.SchedulerTimeType.Stride
   let scheduler: S
    
   func receive<Sub>(subscriber: Sub) 
          where Sub : Subscriber, 
                Upstream.Failure == Sub.Failure, 
                Upstream.Output == Sub.Input {

      var retries = self.retries
      let p = upstream
         .catch { err -> AnyPublisher<Output, Failure> in
            retries -= 1
            return Fail(error: err)
               .delay(for: retries > 0 ? interval : .zero, scheduler: scheduler)
               .eraseToAnyPublisher()
         }
         .retry(self.retries)

      p.subscribe(subscriber)
   }
}

為方便起見,您可以創建一個運算符,就像您在問題中所做的那樣:

public extension Publisher {
    func retryWithDelay<S>(
        retries: Int,
        delay: S.SchedulerTimeType.Stride,
        scheduler: S
    ) -> RetryWithDelay<Self, S> where S: Scheduler {
        
        RetryWithDelay(upstream: self, 
                       retries: retries, delay: delay, scheduler: scheduler)
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM