RxJS 系列 – Error Handling Operators
前言
前几篇介绍过了
这篇继续介绍 Error Handling Operators.
参考
RxJS 錯誤處理 Operators (1) - catchError / finalize / retry / retryWhen
Docs – Error Handling Operators
Observable and Subscriber Handler Error
Observable 的流程是 : Observable init > pipe > subscribe
不经过 pipe 的情况下, 处理 error 的方式如下:
const obs = new Observable(subscriber => { subscriber.error('error message'); // throw 'error message'; // throw 也是可以 }); obs.subscribe({ error: errorMessage => console.log(errorMessage), // error message });
简单明了.
catchError
catchError 是 pipe 阶段的 error handle. 它是 operator 来的.
catch error and change to succeeded
const obs = new Observable(subscriber => { subscriber.error('error message'); }); obs .pipe( catchError(error => { console.log(error); // error message return of('succeeded'); }) ) .subscribe({ next: value => console.log(value), // succeeded error: errorMessage => console.log(errorMessage), // won't call });
catchError 接收到 error 后, 可以有几个处理方式. 上面这个是返回一个 "成功" 的 Observable, 这样 error 就不会在传下去了.
catch error and re-throw
catch error 然后继续往下 throw error,
throwError 方法之前介绍过了, 它是 Creation Operators 的一员.
catchError(error => { return throwError(() => 're-throw error'); // throw 're-throw error'; // 用 throw 也可以 })
小结
总之, catchError 要返回一个 Observable, 可以是 succeeded 或者是 error
catchError(error => { if (Math.random() < 0.5) { return throwError(() => 're-throw error'); // throw 're-throw error'; // 用 throw 也可以 } else { return of('succeeded'); } })
catch error and retry
除了 succeeded 和 error, 还有一种处理方式是 retry. 所谓 retry 就是 unsubscribe 当前的 stream, 重新 subscribe Observable 得到新的 stream (旧的 Observable 会 displose, 新的会 init)
catchError((error, caught) => { return caught; })
返回 catchError 的第二个参数 caught 就表示要 retry. retry 可能会导致死循环的哦.
所以必须要有条件, 避开死循环, 比如:
catchError((error, caught) => { if (Math.random() < 0.5) { return caught; // retry } else { return of('succeeded'); } })
delay retry
catchError((error, caught) => { return timer(2000).pipe(switchMap(() => caught)); })
返回一个 delay 的 Observable 就可以延后 retry 了. 这里用了 switchMap 把 timer 的值换成了 caught observable. (这个 operator 我还没有介绍过的)
retry count
要计算 count 只能开一个外部的 variable 做记入. 或者封装一个自定义 operator. 但更简单的方法是直接用 RxJS 提供的 retry 和 retryWhen operator. 下面会介绍.
retry
用 catchError + caught 实现 retry 太费劲了, 所以 RxJS 封装了 retry operator
retry({ count: 3, delay: 2000, resetOnSuccess: false, })
count 声明可以 retry 多少次
delay 声明 retry 的间隔时间, 有时候 error 是因为 server 繁忙, 只要等 1,2 秒在 retry 发 ajax 就可以解决了.
此外 delay 还支持更复杂的 config. 通过判断 error 和 retryCount 来决定要 delay 多少秒.
我们甚至可以返回 click$ 让 user 点击触发 retry.
也可以直接返回 throwError 结束 retry (即便还没有 hit 到 max retry count), 灵活就对了
delay: (error, retryCount) => timer(2000 * retryCount)
resetOnSuccess 用来表达当 retry 成功以后是否要 reset retry count,默认值是 false,通常 reset 是正确的,所以一般我都是 set 成 true。
有一个场景需要 false,那就是 Angular HttpClient.request upload file 的时候。
httpClient.request upload 的 event dispatch 是这样:
event for upload percentage 10% > 40% > 80% > 100% > response error > retry 1 > 10% 注意这里是 success,不是 error > 40% > 80% > 100% > response error > return 1
为什么不是 retry 2?因为 10% 是 success,然后 resetOnSuccess: true,所以第二次 response error 时,retry count 已经 reset 回到 1 了。
这种情况 resetOnSuccess 就不太合适。
retryWhen
已经废弃了, 改用 retry + delay option 实现吧.
一句话总结
catchError : 在 pipe 中 catch error, 3中处理, 成功, 继续 error, retry
retry : 用 catchError 做 retry 太费劲就有了 retry operator
retryWhen : 废弃了, 改用 retry + delay option 实现.
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 推荐几款开源且免费的 .NET MAUI 组件库
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· 【全网最全教程】使用最强DeepSeekR1+联网的火山引擎,没有生成长度限制,DeepSeek本体
2018-10-02 Angular 学习笔记 ( timezone + moment + material date-picker + date pipe + asp.net core )