RxSwift,Share +重试机制

时间:2018-01-17 17:14:16

标签: swift share rx-swift

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

我把它封装在一个可观察的中。 我有2个请求规则

  

1)同时永远不会有超过1个请求

     

- >我可以使用一个共享运营商

     

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

     

- >我可以使用shareReplay(1)运算符来实现此

当请求失败时出现问题,shareReplay(1)将只重播最新错误而不再重新启动请求。

请求应在下次订阅时重新开始。

有没有人知道如何将其变成Observable链?

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

它只会在我们没有缓存任何内容时生成工作,但我们需要再次使用副作用来实现所需的输出

2 个答案:

答案 0 :(得分:3)

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

出于这个原因 - 发出.error.completed事件的信息流会立即处理,您不会再收到任何活动。

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

  1. 像你刚才那样使用结果类型
  2. 使用.materialize()(如果需要,还可以使用.dematerialize())。这些第一个运算符会将Observable<Element>转换为Observable<Event<Element>>,这意味着不会发出错误并且序列终止,您将获得一个元素,告诉您它是一个错误事件,但没有任何终止。
  3. 您可以在Adam Borek的博客文章中了解有关RxSwift错误处理的更多信息:http://adamborek.com/how-to-handle-errors-in-rxswift/

答案 1 :(得分:1)

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

Observable