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

В RxJS версии 5 следующий код приводит к завершению процесса после трех итераций обеих подписок:

var Rx = require("rxjs");

const published$ = Rx.Observable.interval(1000).publish();

published$.subscribe(index => {
    console.log(`One: ${index}`);

    if (index == 3) throw new Error("ded.");
});

published$.forEach(index => {
    console.log(`Two: ${index}`);
});

published$.connect();

Однако я понял, что ошибка, выданная в следующем обработчике, просто отменит подписку на эту конкретную подписку и не приведет к прекращению действия базового наблюдаемого объекта. Я ожидал, что подписка «Одна» отменит подписку, но интервал продолжит давать результаты для подписки «Две».

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

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

Есть ли способ, не заключая каждую из моих подписок в try / catch, чтобы в моем следующем обработчике было выброшено исключение, чтобы просто отменить подписку на эту ОДНУ подписку и не прервать базовую наблюдаемую?

------------ РЕДАКТИРОВАТЬ ------------

Я нашел поведение, которое ищу, установив для syncErrorThrowable значение true в объекте подписки, возвращаемом параметром subscribe. Кажется, что единственный раз, когда это когда-либо устанавливается в true в кодовой базе, это через оператор «do».

Стоит ли мне воспользоваться этим полем? Я чувствую себя довольно грязным, используя его, но, с другой стороны, мне кажется странным, что оператор «do» имеет другую семантику обработки ошибок, чем обработчик подписки «next».

Вот основной блок кода, на который влияет этот флаг: https://github.com/ReactiveX/RxJS/blob/master/src%2FSubscriber.ts#L132

Если установлено значение false, вызывается этот метод: https://github.com/ReactiveX/RxJS/blob/master/src%2FSubscriber.ts#L179

Если для него установлено значение true, вместо него используется следующий метод: https://github.com/ReactiveX/RxJS/blob/master/src%2FSubscriber.ts#L188

Разница в том, что первый метод повторно генерирует исключение в стеке вызовов, тогда как второй вместо этого распространяет ошибку на последующие подписки.

Почему оператор do распространяет ошибку вперед, а обработчик "next" возвращает ошибку обратно? Мне это кажется странным.


person Community    schedule 02.03.2016    source источник


Ответы (1)


Нет, не используйте это поле. Если вы измените его обратно на true, ваша подписка начнет принимать ошибки.

Это частное состояние, которое мы используем, чтобы узнать, уведомляется ли подписка синхронно (в том же блоке, что и исходный вызов подписки Observable) или асинхронно. Если в одном из обработчиков сообщений подписчика во время синхронного уведомления возникает ошибка, мы откладываем ее повторную выдачу до тех пор, пока не завершим обратный вызов подписки Observable. [1]

Если ваши обработчики выдают ошибки, которые вы хотите перенаправить обработчику onError подписки, настоящее руководство состоит в том, чтобы переместить их в do блок прямо над подпиской.

Нет, я не согласен с таким поведением. Вот несколько ссылок для контекста:

[1] источник: Я написал этот фрагмент кода.

person ptaylor    schedule 03.03.2016