Уроки35. catchError внутри switchMap
Уроки · 35
35. catchError внутри switchMap
Где ставить catchError — критически важно
Из предыдущего урока вы знаете: ошибка летит вверх по pipe, пока не встретит catchError. Но есть тонкость, которую очень важно понимать в реальных приложениях:
Когда ошибка перехвачена, поток в этой точке завершается. Внешний источник, ниже которого был перехват, продолжает жить. Внешний источник, выше которого был перехват, — тоже мёртв.
Два варианта
// ПЛОХО: catchError снаружи — убивает поле поиска
query$.pipe(
switchMap(q => fakeRequest(q)),
catchError(...) // после первой ошибки query$ мёртв
)
// ХОРОШО: catchError внутри switchMap — падает только один запрос
query$.pipe(
switchMap(q => fakeRequest(q).pipe(
catchError(...) // ловим тут — внешний query$ жив
))
)
Реальный сценарий
Поле живого поиска: пользователь ввёл странный запрос, сервер вернул ошибку. Если catchError снаружи — следующий ввод уже не сработает, поток мёртв. Если внутри — упал только один запрос, следующий ввод снова запустит switchMap.
Что нужно сделать
- Внутри функции, переданной в
switchMap, вfakeRequest(query).pipe(...)добавьтеcatchError(error => of('Fallback: ' + query)). - Заметьте:
catchErrorстоит во внутреннем pipe, а не во внешнем. - Ожидаемый вывод:
Result: ok → Fallback: bad → Result: next. После провалаbadпоток жив и обрабатываетnext.
Решение spoiler · click to reveal
const { from, of, throwError, switchMap, catchError } = Rx;
function fakeRequest(query) {
if (query === 'bad') {
return throwError(() => 'Request failed');
}
return of('Result: ' + query);
}
const query$ = from(['ok', 'bad', 'next']);
const result$ = query$.pipe(
switchMap(query => {
return fakeRequest(query).pipe(
catchError(error => of('Fallback: ' + query))
);
})
);
result$.subscribe(value => console.log(value)); script.ts
CONSOLE · Console Output
Нажмите на запуск, чтобы увидеть результат...