异常错误处理
异常处理的难点
虽然必要,但会让代码更加复杂
try / catch
只支持同步,因为 try / catch 是同步执行,执行后里面的异步代码还没有执行,就抓不到异步代码的错误
因此出现 callback,通过传递 cb 参数把异步之后的逻辑传入,相应错误处理也放到异步代码内部,但是有 cbhell 问题
之后出现 Promise,虽然也是传入 cb 处理,但是将 cb 嵌套结构展平成链式结构,解决代码结构问题,但是设计上由于 Promise 最终转换为 fulfilled 或 rejected 态就结束了,重试的逻辑不能由 promise 本身处理
Promise 和 Observable 同属 Monod,Promise 中的 then 相当于 map
RxJS 的异常处理
在函数式编程中,throw new Error()
相当于增加了函数一个新的出口,抛出去的异常可能会导致副作用,导致函数不纯
同时从 caller 的角度,不仅需要处理返回值,还有处理可能的异常,这更加重了 caller 的负担
在 $ 中,异常只会在自己的管道中处理掉,或是流到下游通过 theObserver.error 处理,不会影响其他的流或是全局的状态
管道中的处理分为恢复和重试:
恢复:虽然产生了错误,但是依然让运算进行下去,比如通过 defaultValue
重试:要有上限,最终不行还是要用恢复
catchError 恢复
selector: a function that takes as arguments err, which is the error, and caught, which is the source observable, in case you'd like to "retry" that observable by returning it again. Whatever observable is returned by the selector will be used to continue the observable chain
用作重试:
1of(1, 2, 3, 4, 5).pipe(2 map(n => {3 if (n === 4) {4 throw 'four!'5 }6 return n7 }),8 catchError((err, caught$) => caught$),9 take(10),10).subscribe(x => console.log(x))11// 1, 2, 3, 1, 2, 3, 1, 2, 3, 1
给 theObserver.error 处理:
1of(1, 2, 3, 4, 5).pipe(2 map(n => {3 if (n === 4) {4 throw 'four!'5 }6 return n7 }),8 catchError((err, caught$) => {9 throw err10 }),11).subscribe(console.log, console.error)
retry 重试
retry<T>(count: number = -1): MonoTypeOperatorFunction<T>
retry 是立即执行重试的,有时需要等到某个时机再重试:retryWhen
Returns an Observable that mirrors the source Observable with the exception of an error. If the source Observable calls error, this method will emit the Throwable that caused the error to the Observable returned from notifier. If that Observable calls complete or error then this method will call complete or error on the child subscription. Otherwise this method will resubscribe to the source Observable.
1error$.pipe(2 ((max) => retryWhen(err$ => err$.pipe(3 scan((errorCount, error) => {4 if (errorCount >= max) throw error5 return errorCount + 16 })7 )))(3),8) // retry(3)
同样可以抽象出延迟并有上限的重试等其他操作符
finalize
Callback will call a specified function when the source terminates on complete or error.
重试的本质
重新订阅,先退订然后再订阅