首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >RxSwift,共享+重试机制

RxSwift,共享+重试机制
EN

Stack Overflow用户
提问于 2018-01-17 17:14:16
回答 2查看 1.8K关注 0票数 1

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

我把它封装在一个可以观察的地方。我对这个请求有两条规则

( 1)同时提出的请求不可能超过1项 ->,我可以使用一个共享操作符 2)请求成功后,我不想再次重复相同的请求,只返回最新的值 -> I可以为此使用shareReplay(1)运算符

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

请求应在下一次订阅时重新启动。

有人知道我怎么能把它变成可观察的链吗?

代码语言:javascript
复制
// 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方式实现这一点?

代码语言:javascript
复制
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()

它只在没有缓存任何内容的情况下生成工作,但同样地,我们需要使用副作用来实现所需的输出。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-01-18 16:22:49

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

由于这个原因--一个发出.error.completed事件的流将立即释放,您将不会在那里接收到任何事件。

解决这一问题的方法有两种:

  1. 像刚才一样使用结果类型
  2. 使用.materialize() (如果需要的话使用.dematerialize() )。这些第一个操作符将您的Observable<Element>转换为Observable<Event<Element>>,这意味着您将得到一个元素,它告诉您这是一个错误事件,但没有任何终止,而不是发出错误和终止序列。

您可以在Adam关于以下内容的伟大博客文章中更多地了解RxSwift中的错误处理:http://adamborek.com/how-to-handle-errors-in-rxswift/

票数 5
EN

Stack Overflow用户

发布于 2018-01-17 22:49:23

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

代码语言:javascript
复制
safeObservable
    .flatMap {
        Requestor
            .makeUnsafeObservable()
            .catchErrorJustReturn(0)
    }
    .shareReplay(1)
    .subscribe()
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48306567

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档