例如下面这段代码
fromEvent(document, 'click').pipe( map(i => { console.log('click') throw new Error('error') }) ).subscribe({ next: console.log, complete: () => console.log('complete'), error: (err) => console.log(err) })
我以为的输出:点一下输出 click 和 error ,再点还输出 click 和 error
实际上的输出:点一下输出 click 和 error ,再点就没反应了
就算用 catchError 也一样会被关闭
事件倒还好,加个 retry 就行了,of 之类还得用 map 包起来
例如想输出 1 3 不能这么写
of(1, 2, 3).pipe( map(i => { if (i === 2) { throw new Error('error') } return i; }), catchError(err => EMPTY) ).subscribe({ next: console.log, complete: () => console.log('complete'), error: (err) => console.log(err) })
要这么写用 map 包起来
of(1, 2, 3).pipe( switchMap(i => { return of(i).pipe( map(i => { if (i === 2) { throw new Error('error') } return i; }), catchError(i => EMPTY) ) }) ).subscribe({ next: console.log, complete: () => console.log('complete'), error: (err) => console.log(err) })
为啥要这么设计?出来个错误把整个管子都给扬了。
RxJS 实际的业务都是怎么写的,都是加 retry 或者拿 map 包起来吗?总不能在所有 map 里写 try catch 吧。
补充一下,其实用 catchError 也可以,但是只有fromEvent 事件这类的才行。
fromEvent(document, 'click').pipe( map(() => { console.log('click') throw new Error('error') }), catchError((err, caught) => caught) ).subscribe({ next: console.log, complete: () => console.log('complete'), error: (err) => console.log(err) })
封装一个pipe供使用(供参考未测试,不清楚是否通用)
另附各种跳过继续运行的尝试解决方案参考
https://iamturns.medium.com/continue-rxjs-streams-when-errors-occur-c6a031f9a6cf
function tryCatch(tryPipe, catchCallback) { return pipe( switchMap(i => of(i).pipe(tryPipe, catchError(err => catchCallback(err)))) ) } of(1, 2, 3).pipe( tryCatch( pipe( map(i => { if (i === 2) { throw new Error('err') } return i }) ), err => EMPTY, ) ).subscribe({ next: console.log, complete: () => console.log('complete'), error: (err) => console.log('error', err) }) // 输出 1 3
![]() | 1 66450146 2023-10-20 20:54:07 +08:00 via iPhone |
2 Magentaize 2023-10-21 09:31:57 +08:00 via iPhone ![]() materialize 了解一下 |
![]() | 3 vaporSpace 2023-10-21 11:12:00 +08:00 ``` js of(1, 2, 3) .pipe( switchMap((n) => of(n).pipe( map((o) => { if (o === 2) { throw 'error'; } return o; }), catchError(() => of('EMPTY')) ) ) ) .subscribe((x) => console.log(x)); ``` 达到效果,就是有点丑 |
4 yor1g 2023-10-21 12:40:15 +08:00 EMPTY 直接走 complete 了吧 catch 返回正常值才能不会断流 |
![]() | 5 Helsing 2023-10-21 15:09:32 +08:00 via iPhone ![]() 二楼说的 materialize 和 dematerialize 操作符是比较好处理方案 |
![]() | 6 DingJZ 2023-10-23 10:15:04 +08:00 借楼问个问题,怎么能把 rx 代入日常的开发中,学了 n 次了,基本上每次用的时候现学现写,后面就忘了,下次再重来 |