Почему Rx.Observable.throw(x) на самом деле не выбрасывает?

Я играю с Rxjs, наблюдаемыми объектами и картами и обнаружил странное поведение Observable.throw(error), которое не могу объяснить.

Если у меня есть поток Rx, который использует оператор карты, и я хочу прервать процесс, я бы ожидал, что метод Observable.throw будет подходящим, однако, похоже, это не так.

Рассмотрим следующий пример:

Rx.Observable.just("test 1").subscribe(
    x => console.log(x),
  err => console.log(err),
  () => console.log("done, no errors")
);

Теперь давайте представим ошибку, если я использую обычный throw из Javascript, он работает как положено:

Rx.Observable.just("test 2").map(
    x => { throw new Error(x) }
).subscribe(
    x => console.log(x),
  err => console.log(err),
  () => console.log("done - error was thrown, as expected")
);

Вывод:

Ошибка: тест 2 в Rx.Observable.just.map.x ((index):58) в c (rx.all.compat.js:61) в e.onNext (rx.all.compat.js:5169) ( ...)

Но если я использую Rx.Observable.throw(...), обратный вызов error от следующего подписчика никогда не вызывается, а вместо этого будет вызываться обратный вызов next с каким-то странным объектом, который кажется объектом ошибки Rx.

Rx.Observable.just("test 3").map(
    x => Rx.Observable.throw(x)
).subscribe(
    x => console.log(x),
  err => console.log(err),
  () => console.log("done - it does not work... why?")
);

Вывод:

b_subscribe: f(a)ошибка: "тест 3" планировщик: a__proto__: g

Как указал @Whymarrh, кажется, что он работает нормально, если вместо этого я использую оператор flatMap.

Документация для карты:

Оператор Map применяет выбранную вами функцию к каждому элементу, испускаемому исходным Observable, и возвращает Observable, который испускает результаты применения этих функций.

Документация для Observable.throw:

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

Кто-нибудь знает, почему при использовании Observable.throw внутри оператора карты не вызывается обратный вызов error и почему процесс не прерывается?

Пример в jsfiddle

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

Небольшое напоминание: в stackoverflow действует политика вежливости.


person yms    schedule 07.02.2017    source источник
comment
Мне кажется, что использование flatMap работает (и это было бы ожидаемым решением): jsbin.com/bododomeku /edit?js,console (здесь я использую JS Bin, чтобы иметь удобный вывод на консоль.)   -  person Whymarrh    schedule 08.02.2017
comment
Я проголосовал за закрытие проблемы, поскольку она вызвана проблемой, которую больше нельзя воспроизвести, или простой типографской ошибкой. Хотя здесь могут быть похожие вопросы, этот вопрос был решен таким образом, который вряд ли поможет будущим читателям. (Выделено мной.) Извините, я не думаю, что здесь есть что-то особенное, вы действительно не читали вывод. Даже если вы переформулируете вопрос, чтобы спросить, почему возврат Observable не работает должным образом с map, будет куча дубликатов, которые предлагают flatMap в качестве решения.   -  person Whymarrh    schedule 08.02.2017
comment
Чтобы продолжить ваше редактирование, flatMap — это оператор, который вам нужен, если вы хотите вернуть Observable (Rx.Observable.throw(error)) вместо значения (throw new Error()). Использование map приведет к вызову onNext с потоком, в котором есть ошибка.   -  person Whymarrh    schedule 08.02.2017
comment
Ах, извините, тогда это дубликат stackoverflow.com/q/33471526/1267663 (хотя я бы рекомендовал stackoverflow.com/a/33258858/1267663, так как это лучший ответ)   -  person Whymarrh    schedule 08.02.2017
comment
Если вы чувствуете, что это не дубликат, я думаю, вам нужно значительно отредактировать вопрос, чтобы сделать его таким   -  person Whymarrh    schedule 08.02.2017
comment
@yms throw генерирует исключение, которое просто всплывает вверху процесса. Observable.throw просто создает структуру, представляющую ошибку. Для map это значение, как и любое другое, для вызова обработчика успеха. Чтобы flatMap, он имел структуру и был развернут, чтобы вызвать обработчик ошибок.   -  person Bergi    schedule 08.02.2017
comment
См. также namitamalik.github.io/Map-vs-FlatMap.   -  person Bergi    schedule 08.02.2017
comment
Как вы думаете, я должен снова открыть и опубликовать свои комментарии в качестве ответа? Кстати, для независимого от языка представления проверьте это   -  person Bergi    schedule 08.02.2017


Ответы (1)


Один из комментариев правильно отвечает на этот вопрос:

throw new Error(x) генерирует исключение, которое просто всплывает вверху процесса.

x => Rx.Observable.throw(x) просто создает структуру, представляющую ошибку. Для оператора map эта структура является таким же значением, как и любая другая, для вызова обработчика успеха. flatMap, с другой стороны, возьмет структуру и развернет ее, а затем вызовет обработчик ошибок.

person Community    schedule 18.08.2017