Я новичок в RxJS и не могу понять, как передаются параметры:
import { catchError, map, Observable, of } from 'rxjs';
let obs$ = of(1,2,3,4,5);
obs$.pipe(
map(n => {
if (n === 4) {
throw 'bloody hell'
}
return n;
}),
catchError(handleError())
).subscribe(x => console.info(x));
function handleError() {
return (err: any, caught: Observable<any>): Observable<string> => {
console.info('error is ', err);
return of('I', 'II') ;
}
}
Выход
$ node build/catch-me.js
1
2
3
error is bloody hell
I
II
Теперь, когда я смотрю на функцию catchError, она говорит:
export function catchError<T, O extends ObservableInput<any>>(
selector: (err: any, caught: Observable<T>) => O
): OperatorFunction<T, T | ObservedValueOf<O>>;
Мои вопросы:
HandleError — это функция, которая возвращает функцию. Эта функция передается в catchError. Это то же самое, что
catchError((err: any, caught: Observable<any>): Observable<string> => {
console.info('error is ', err);
return of('I', 'II') ;
})
Так как это функция handleError возвращает.
Мои вопросы: Как handleError волшебным образом получает значения err и catch из функции catchError? Никуда не передается?
Функция catchError не имеет прямого отношения к «значению ошибки и перехвата». Да, но только статически. Ему просто нужно вернуть функцию правильного типа.
Или, если вы Haskell Curry, вы можете сказать, что handleError принимает свои аргументы отдельно, и вы видите только частичное приложение. Возврат приложения происходит внутри catchError Учтите следующее:
function add(a,b) {
return a + b;
}
function curry_add(){
return a => b => a + b;
}
const ten = add(9,1);
const alsoTen = curry_add()(9)(1);
Curry_add волшебным образом не получает никаких параметров. Это то же самое, что и add, но требуется 3 приложения, прежде чем вы сможете получить номер.
Почему значения err и catch доступны только в функции возврата handleError?
Снова частичное приложение, вы можете думать о них как о втором приложении handleError, если хотите. Предоставление вам этих значений является работой оператора catchError, поэтому вы выполняете первое приложение, а оператор выполняет второе за кулисами.
Передаются ли два типа: один — тип наблюдаемого, второй — ObservableInput?
Ошибка и наблюдаемая величина, вызвавшая ошибку.
Как понять, какая операторная функция возвращается из catchError? Наконец, возвращается наблюдаемая величина со значениями I, II.
OperatorFunction преобразует наблюдаемую. Функция pipe знает, как работать только с OperatorFunction, поэтому каждый оператор в конечном итоге создает OperatorFunction. Таким образом, map, tap, switchMap, catchError и т. д. должны создать для вас OperatorFunction. Вы можете просто создать его самостоятельно, если хотите.
Например:
function filterFours(a: Observable<number>): Observable<number> {
return new Observable(observer => {
const sub = a.subscribe({
next: v => {
if (v != 4) observer.next(v);
},
complete: () => observer.complete(),
error: e => observer.error(e)
});
return {
unsubscribe: () => sub.unsubscribe()
};
})
}
of(1,4,2,4,3,4,5,4).pipe(
filterFours
).subscribe(console.info);
Это семантически то же самое:
of(1,4,2,4,3,4,5,4).pipe(
filter(v => v != 4)
).subscribe(console.info);
То, что возвращает filter(v => v != 4), — это то же самое, что и filterFours. Они делают то же самое.
Отличный пример с карри. Спасибо за подробные разъяснения