Наблюдаемое rxjs не завершается при возникновении ошибки

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

var observer = Rx.Observable.create(function(observer){
    observer.onError(new Error('no!'));
    observer.onCompleted();
})

observer.subscribe(
    function(x) { console.log('succeeded with ' + x ) },
    function(x) { console.log('errored with ' + x ) },
    function() { console.log('completed') }
)

Вывод:

errored with Error: no!

Я ожидаю, что это будет:

errored with Error: no!
completed

Если я изменил код, чтобы вызывать onNext вместо onError, наблюдаемый правильно завершает:

var observer = Rx.Observable.create(function(observer){
    observer.onNext('Hi!');
    observer.onCompleted();
})

observer.subscribe(
    function(x) { console.log('succeeded with ' + x ) },
    function(x) { console.log('errored with ' + x ) },
    function() { console.log('completed') }
)

Я получаю ожидаемый результат:

succeeded with Hi! 
completed

Почему он не завершается при возникновении ошибки?

Ответ 1

Это потому, что ошибка означает завершение, поэтому обратный вызов, связанный с onCompleted, никогда не вызывается. Вы можете просмотреть здесь контракт Rxjs для наблюдаемых (http://reactivex.io/documentation/contract.html):

Наблюдаемый может делать ноль или больше уведомлений OnNext, каждый из которых представляет собой один испускаемый элемент, и затем он может следовать этим уведомлениям об эмиссии посредством уведомления OnCompleted или OnError, но не обоих. После выпуска уведомления OnCompleted или OnError оно не может впоследствии выдавать какие-либо дополнительные уведомления.

Для управления ошибками вы можете посмотреть: https://github.com/Reactive-Extensions/RxJS/blob/master/doc/gettingstarted/errors.md

Ответ 2

Пока у меня был тот же вопрос, я столкнулся с этой проблемой github.

В этом случае должен использоваться метод finally объекта Observable.

Цитата из Aleksandr-Leotech из этого потока:

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

Это не очевидно с запросами HTTP, но представьте себе два дополнительных сценарии.

  • События мыши. Вы получите бесконечный успех обратные вызовы, но вы никогда не получите окончательного или полного, потому что пользовательские события никогда не остановятся (если вы не инициируете исключение с buggy code, тогда вы получите ошибку и, наконец,).

  • Работа с веб-сокетами. Вы получите множественные обратные вызовы с несколькими успехами, но в какой-то момент ваше общение с задним концом остановится, и вы получите как полный, так и окончательный, если у вас нет ошибок, которые вызовут ошибку и, наконец,.

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