RxJS 为什么设计成抛出错误后直接关闭 Observer,不再发出值?实际的业务代码都是怎么处理异常错误的?

202 天前
 rabbbit

例如下面这段代码

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 吧。

1486 次点击
所在节点    程序员
6 条回复
66450146
202 天前
如果有这个需要的话,把元素弄成 Result 不就得了

https://github.com/badrap/result
Magentaize
201 天前
materialize 了解一下
vaporSpace
201 天前
``` 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));
```

达到效果,就是有点丑
yor1g
201 天前
EMPTY 直接走 complete 了吧 catch 返回正常值才能不会断流
Helsing
201 天前
二楼说的 materialize 和 dematerialize 操作符是比较好处理方案
DingJZ
199 天前
借楼问个问题,怎么能把 rx 代入日常的开发中,学了 n 次了,基本上每次用的时候现学现写,后面就忘了,下次再重来

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/983900

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX