RxSwift,共享+重试机制



我有一个可以成功或失败的网络请求

我已将其封装在可观察量中。 我有 2 条请求规则

1) 同时不能有超过 1 个请求

->有一个共享运算符,我可以为此使用

2)当请求成功时,我不想重复相同的内容 再次请求并返回最新值

-> 我可以为此使用 shareReplay(1) 运算符

当请求失败时出现问题, shareReplay(1) 只会重放最新的错误,不会再次重新启动请求。

请求应在下一个订阅时再次开始。

有没有人知道我如何将其变成可观察链?

// scenario 1
let obs: Observable<Int> = request().shareReplay(1)
// outputs a value
obs.subscribe()
// does not start a new request but outputs the same value as before
obs.subscribe() 
// scenario 2 - in case of an error
let obs: Observable<Int> = request().shareReplay(1)
// outputs a error
obs.subscribe() 
// does not start a new request but outputs the same value as before, but in this case i want it to start a new request
obs.subscribe() 

这似乎完全是我想要的,但它包括将状态保持在可观察范围之外,有人知道我如何以更 Rx 的方式实现这一目标吗?

enum Err: Swift.Error {
case x
}
enum Result<T> {
case value(val: T)
case error(err: Swift.Error)
}
func sample() {
var result: Result<Int>? = nil
var i = 0
let intSequence: Observable<Result<Int>> = Observable<Int>.create { observer in
if let result = result {
if case .value(let val) = result {
return Observable<Int>.just(val).subscribe(observer)
}
}
print("do work")
delay(1) {
if i == 0 {
observer.onError(Err.x)
} else {
observer.onNext(1)
observer.onCompleted()
}
i += 1
}
return Disposables.create {}
}
.map { value -> Result<Int> in Result.value(val: value) }
.catchError { error -> Observable<Result<Int>> in
return .just(.error(err: error))
}
.do(onNext: { result = $0 })
.share()
_ = intSequence
.debug()
.subscribe()
delay(2) {
_ = intSequence
.debug()
.subscribe()
_ = intSequence
.debug()
.subscribe()
}
delay(4) {
_ = intSequence
.debug()
.subscribe()
}
}

sample()

它仅在我们没有任何缓存时生成工作,但同样我们需要使用副作用来实现所需的输出

如前所述,RxSwift错误需要被视为致命错误。它们是您的流通常无法恢复的错误,通常是用户甚至不会面临的错误。

因此,发出.error.completed事件的流将立即释放,并且您不会再在那里收到任何事件。

有两种方法可以解决此问题:

  1. 像刚才一样使用结果类型
  2. 使用.materialize()(如果需要,可以使用.dematerialize())。第一个运算符将把你的Observable<Element>变成一个Observable<Event<Element>>,这意味着你不会发出错误并终止序列,而是得到一个元素,告诉你这是一个错误事件,但没有任何终止。

您可以在 Adam Borek 的精彩博客文章中阅读有关 RxSwift 错误处理的更多信息:http://adamborek.com/how-to-handle-errors-in-rxswift/

如果Observable序列发出错误,则它永远无法发出另一个事件。但是,使用flatMap将容易出错的Observable包装在另一个Observable中并在允许它们传播到外部Observable之前捕获任何错误是一种相当普遍的做法。例如:

safeObservable
.flatMap {
Requestor
.makeUnsafeObservable()
.catchErrorJustReturn(0)
}
.shareReplay(1)
.subscribe()