FlatMapПоследний с повтором - PullRequest
1 голос
/ 16 апреля 2020

У меня есть ситуация, когда у меня есть три наблюдаемые, которые отображаются в поток результатов.

Первая наблюдаемая говорит мне, из каких двух других наблюдаемых мне следует принимать значения. При каждом излучении первой наблюдаемой поток результатов переключается на излучение плоской карты соответствующей наблюдаемой.

Эту ситуацию обычно можно выполнить с помощью flatMapLatest.

Однако при каждый переключатель flatMap, я также хочу воспроизвести последнее устаревшее значение. Это проблема, потому что flatMapLatest не предоставляет возможности для воспроизведения старых значений существующих наблюдаемых.

См. Ниже RxMarbles того, что я хочу сделать sh:

RxMarbles

Я пытался использовать shareReplay(N), как показано в коде ниже, но, похоже, это не решает проблему.

    let Observable1Replay = Observable1.share(replay: 1, scope: .forever)

    let Observable2Replay = Observable2.share(replay: 1, scope: .forever)

    let resultObservable = Observable3
        .flatMapLatest { boolValue in
            if boolValue == true {
               return Observable1Replay
            } else {
               return Observable2Replay
            }
        }

1 Ответ

0 голосов
/ 16 апреля 2020

Когда вы застряли, вы всегда можете свернуть свое и вернуться к нему позже:

func example(source: Observable<String>, obs1: Observable<String>, obs2: Observable<String>) -> Observable<String> {
    return Observable.create { observer in
        let lock = NSRecursiveLock()
        var last1 = ""
        var last2 = ""
        var isFirst = false
        var completeCount = 3
        let srcSub = source.subscribe { event in
            lock.lock(); defer { lock.unlock() }
            switch event {
            case .next:
                isFirst = !isFirst
                if isFirst && !last1.isEmpty {
                    observer.onNext(last1)
                }
                else if !isFirst && !last2.isEmpty {
                    observer.onNext(last2)
                }
            case .error(let error):
                observer.onError(error)
            case .completed:
                completeCount -= 1
                if completeCount == 0 {
                    observer.onCompleted()
                }
            }
        }
        let obs1Sub = obs1.subscribe { event in
            lock.lock(); defer { lock.unlock() }
            switch event {
            case .next(let element):
                if isFirst {
                    observer.onNext(element)
                }
                last1 = element
            case .error(let error):
                observer.onError(error)
            case .completed:
                completeCount -= 1
                if completeCount == 0 {
                    observer.onCompleted()
                }
            }
        }
        let obs2Sub = obs2.subscribe { event in
            lock.lock(); defer { lock.unlock() }
            switch event {
            case .next(let element):
                if !isFirst {
                    observer.onNext(element)
                }
                last2 = element
            case .error(let error):
                observer.onError(error)
            case .completed:
                completeCount -= 1
                if completeCount == 0 {
                    observer.onCompleted()
                }
            }
        }
        return CompositeDisposable(srcSub, obs1Sub, obs2Sub)
    }
}
...