#rx-swift #combinelatest
#rx-swift #combinelatest
Вопрос:
Я вижу некоторые неожиданные результаты при использовании combineLatest для коллекции холодных наблюдаемых. Он генерирует последние из всех, кроме последнего наблюдаемого, и вместо этого объединяет последние из первых (n-1) наблюдаемых с каждым элементом из n-го наблюдаемого.
let observable = ReplaySubject<Int>.createUnbounded()
let observable2 = ReplaySubject<String>.createUnbounded()
observable.onNext(1)
observable.onNext(2)
observable.onNext(3)
observable.onNext(4)
observable2.onNext("bed")
observable2.onNext("book")
observable2.onNext("table")
let latestObserver = Observable.combineLatest(observable, observable2)
_ = latestObserver
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
Выдает вывод:
(4, «кровать»)
(4, «книга»)
(4, «таблица»)
Я ожидал увидеть вывод только (4, «таблица»).
Если я изменю порядок наблюдаемых следующим образом:
let latestObserver = Observable.combineLatest(observable2, observable)
Я получаю вывод:
(«таблица», 1)
(«таблица», 2)
(«таблица», 3)
(«таблица», 4)
Если я добавлю окончательный произвольный наблюдаемый, то я увижу только последний из каждого из первых:
let observable = ReplaySubject<Int>.createUnbounded()
let observable2 = ReplaySubject<String>.createUnbounded()
let observable3 = Observable<Int>.just(42)
observable.onNext(1)
observable.onNext(2)
observable.onNext(3)
observable.onNext(4)
observable2.onNext("bed")
observable2.onNext("book")
observable2.onNext("table")
let latestObserver = Observable.combineLatest(observable, observable2, observable3)
_ = latestObserver
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
выдает вывод: (4, «таблица», 42)
Действительно ли это ожидаемое поведение?
Комментарии:
1. Исходя из этого вопроса и вашего последнего, у меня создается впечатление, что у вас возникли проблемы с отслеживанием того, какие наблюдаемые являются синхронными, а какие асинхронными…
2. @DanielT. Действительно. Не вдаваясь в подробности, это вытекает из спецификации протокола модели в качестве входных данных для контроллера представления. Протокол определяет наблюдаемые объекты, в которых я ранее привык видеть BehaviorRelay или BehaviourSubject . Контроллер представления должен обновлять свой дисплей и элементы управления только из последних значений и игнорировать любые промежуточные воспроизводимые значения. Просто пытаюсь понять последствия различных возможных будущих конкретных реализаций протокола, которые могут быть вне моего контроля. Я думал, что понял вещи, но обнаружил некоторые сюрпризы. Спасибо
3. Ах, я понимаю… В любом случае вам следует избегать использования subjects (включая ReplaySubject .) Возможно, это поможет вам избежать выделения всех этих «промежуточных значений воспроизведения» в первую очередь. Объекты следует использовать только для преобразования кода, отличного от Rx, в Rx и для обработки циклов зависимостей (где выходные данные наблюдаемого могут влиять на его собственные входные данные).
Ответ №1:
Давайте разберем, что происходит в вашем первом примере…
Вы могли бы использовать Observable.from
вместо subject и получить те же результаты… Шаги в коде следующие,
- создайте два
ReplaySubject
s и загрузите их событиями. combineLatest
Оператор подписывается на первый объект.- Этот первый объект немедленно воспроизводит все свои значения.
- Поскольку второй объект еще не подписан,
combineLatest
оператор ничего не генерирует, вместо этого он молча поглощает значения, всегда сохраняя «последнее». - Затем
combineLatest
оператор подписывается на второй объект. - При этом воспроизводятся все его значения.
- Поскольку
combineLatest
оператор теперь получил следующее событие от каждого из своих источников, он генерирует значения, переданные из второго источника, в сочетании с последним (т. Е. Последним) из первого источника.
Ваши объекты воспроизведения по своей сути синхронны. Они передают все значения подписчику сразу после подписки.
В вашем последнем примере кода, поскольку последнее наблюдаемое из трех выдает только одно значение и только после того, как два других выдали все свои значения, вы видите только один вывод, содержащий последнее из двух предыдущих наблюдаемых.