RxJS catchError 参数传递与原理新手疑问解析
示例代码
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.log(x)); function handleError() { return (err: any, caught: Observable<any>): Observable<string> => { console.log('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>>;
疑问解答
1. 未显式传递参数,handleError如何从catchError获取err和caught值?
你调用handleError()时,它返回的是一个函数,这个函数才是catchError要求的selector参数。当管道中抛出错误时,RxJS内部会自动将err(错误对象)和caught(原Observable)传入这个返回的函数——不需要你手动传递,这是RxJS内部的逻辑处理。简单说,handleError是个"工厂函数",用来生成符合错误处理要求的函数。
2. 为何err和caught值仅在handleError返回的函数中可用?
因为handleError()执行的时候,错误还没发生,自然拿不到这两个值。只有当管道触发错误逻辑时,RxJS才会调用handleError返回的内层函数,此时才会传入实际的err和caught,所以这两个值只能在这个内层函数中访问。
3. 是否存在两种传入类型:Observable的类型与ObservableInput?
是的。ObservableInput是RxJS定义的类型别名,涵盖了所有可转换为Observable的类型,包括Observable本身、Promise、数组、迭代器、单个值等。catchError的selector返回值可以是ObservableInput类型,RxJS会自动将其转换为Observable继续流处理;而Observable是其中最基础的核心类型。
4. 如何理解catchError返回的OperatorFunction?为何最终返回包含'I'、'II'的Observable?
OperatorFunction<T, R>本质是一个函数,接收Observable<T>并返回Observable<R>——这是RxJS管道操作符的标准形态,用于将原Observable转换为新的Observable。
当流抛出错误时,catchError会调用你传入的selector函数(即handleError返回的函数),该函数返回了of('I', 'II')这个Observable。catchError会用这个新Observable替换出错的原Observable,因此后续订阅会接收这个新Observable发出的'I'和'II',这就是输出中出现它们的原因。
内容的提问来源于stack exchange,提问作者lopah elision

