#rxjs #rxjs-observables
#rxjs #rxjs-наблюдаемые
Вопрос:
При работе с concatMap, как я могу прервать выполнение наблюдаемых дальше по строке и предотвратить вызов обработчика завершения?
Вот простой пример.
of(...[1, 2, 3]).pipe(
concatMap(t => of(t)),
map(n => {
console.log(n);
if (n === 2) {
throw new Error('OK, fail here');
}
}),
catchError((e, c) => of(console.log('Caught ' e)))
)
.subscribe(
{
complete: () => console.log('Complete should not be triggered in an error case, but here it is'),
error: (err: any) => {
console.log('I did never trigger, thats ok!');
}
});
Наблюдаемый источник выдает 1,2,3, который передается в concatMap.
Возможны два сценария: все три наблюдаемых генерируются без ошибок, в этом случае должен быть запущен полный обработчик. Или другой случай, изображенный здесь: где-то в конце строки возникает ошибка, например, когда n === 2. concatMap прекращает выполнение следующего наблюдаемого, что идеально, но все равно запускает обработчик завершения, что нежелательно.
Фактический результат
1 2 Обнаруженная ошибка: ОК, сбой здесь Завершение не должно запускаться в случае ошибки, но вот оно
Желаемый результат
1 2 Обнаруженная ошибка: ОК, сбой здесь
Какие-либо подсказки? Моей предыдущей попыткой было запустить следующий обработчик, но это оказалось действительно плохо:/ поскольку это вызвало hostReportError
Ответ №1:
Хорошо, поскольку я смог самостоятельно ответить на все другие интересные вопросы, касающиеся RxJS, поехали 🙂
Помните: catchError
заменяет ошибочный наблюдаемый объект каким-либо другим наблюдаемым объектом. catchError
Поэтому, если бы возвращался наблюдаемый через throwError
, это остановило бы выполнение и, что еще лучше, это вызвало бы обработчик ошибок, который раньше был простаивающим.
of(...[1, 2, 3]).pipe(
concatMap(t => of(t)),
map(n => {
console.log(n);
if (n === 2) {
throw new Error('OK, fail here');
}
}),
catchError((e, c) => throwError(e)) // This line has changed
)
.subscribe(
{
complete: () => console.log('Complete should not be triggered in an error case, but here it is'),
error: (err: any) => {
console.log('Now I have something to do, yay!');
}
});
Комментарии:
1. Здесь вам вообще не нужен
catchError
оператор. Каждый оператор эффективно окружен блоком try-catch и превращает поток в поток с ошибкой, если генерируется исключение.throw new Error('OK, fail here');
уже вызовет вашerror
обратный вызов в вашей подписке. Который, если подумать, должен работать, поскольку это тот же обратныйcatchError
вызов, к которому подключается оператор.