[英]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.