Open findxc opened 9 months ago
直接看官方文档的解释: https://rxjs.dev/guide/overview
我的理解: RxJS 是一个针对异步场景的工具库。如果你的项目中异步场景相对复杂,那么你会觉得这个工具好用,值得花时间学习,可以通过 一个 RxJS 实际应用的例子 感受一下。
对于复杂的异步场景,使用 RxJS 更容易写出“高内聚”的代码(更少的变量定义,更集中的逻辑)。
(但是不得不说,用 RxJS 很容易写出 bug ,所以对于复杂异步场景,还有更简洁的解决方案吗?🤔)
每次写下 .subscribe() 的时候,我们都要想想,需要写对应的 .unsubscribe() 代码吗?更多细节见 RxJS 使用时的取消订阅问题 。
.subscribe()
.unsubscribe()
每次写下 .subscribe() 的时候,还需要想想,我们需要做错误处理吗?
比如下面这段代码,每次点击后会去发一个请求。那么,如果某次点击时,刚好这次 API 请求失败了,下一次再点击,还会发请求吗?答案是不会,因为请求失败使得整个 Observable 进入了 error 状态,不会再 next 值了。
fromEvent(this.button.nativeElement, 'click') .pipe(switchMap(() => this.http.get('/users'))) .subscribe()
所以如果希望某次请求的失败不会影响后面的请求,需要加上 catchError 来处理异常,并且请注意这个 catchError 需要加在 this.http.get('/users') 这个 Observable 上才行。
catchError
this.http.get('/users')
fromEvent(this.button.nativeElement, 'click') .pipe(switchMap(() => this.http.get('/users').pipe(catchError(() => of([]))))) .subscribe()
补充关于 Observable 状态的两个概念:
比如我们 subscribe 的这个 Observable 什么时候会 next 值,什么时候会 error ,什么时候会 complete ,细节是魔鬼,确认过细节后你才能确定代码的执行是符合你的预期的。
比如 a$.pipe(combineLatestWith(b$)).subscribe(v => console.log(v)) ,如果 a$ next 值了,我们能看到 console 吗?如果 b$ 也 next 值了,我们能看到 console 吗?如果 b$ 又 next 值了,我们能看到 console 吗?以及哪些情况会 error ?
a$.pipe(combineLatestWith(b$)).subscribe(v => console.log(v))
a$
b$
.value
null
filter
没啥特殊需求就 Subject ;如果希望设置初始值或者希望能直接拿到当前值,那么就用 BehaviorSubject ;如果希望能记录旧值但是不需要设置初始值那就 ReplaySubject ,但是要注意 ReplaySubject 和 Subject 一样不能直接拿到值,只能通过 subscribe 来拿到值。
a$ = b$.pipe(xxx)
xxx$ | async
What is RxJS & Why we need RxJS
直接看官方文档的解释: https://rxjs.dev/guide/overview
我的理解: RxJS 是一个针对异步场景的工具库。如果你的项目中异步场景相对复杂,那么你会觉得这个工具好用,值得花时间学习,可以通过 一个 RxJS 实际应用的例子 感受一下。
对于复杂的异步场景,使用 RxJS 更容易写出“高内聚”的代码(更少的变量定义,更集中的逻辑)。
(但是不得不说,用 RxJS 很容易写出 bug ,所以对于复杂异步场景,还有更简洁的解决方案吗?🤔)
实际使用时需要注意的问题
取消订阅
每次写下
.subscribe()
的时候,我们都要想想,需要写对应的.unsubscribe()
代码吗?更多细节见 RxJS 使用时的取消订阅问题 。错误处理
每次写下
.subscribe()
的时候,还需要想想,我们需要做错误处理吗?比如下面这段代码,每次点击后会去发一个请求。那么,如果某次点击时,刚好这次 API 请求失败了,下一次再点击,还会发请求吗?答案是不会,因为请求失败使得整个 Observable 进入了 error 状态,不会再 next 值了。
所以如果希望某次请求的失败不会影响后面的请求,需要加上
catchError
来处理异常,并且请注意这个catchError
需要加在this.http.get('/users')
这个 Observable 上才行。补充关于 Observable 状态的两个概念:
仔细测试 Observable
比如我们 subscribe 的这个 Observable 什么时候会 next 值,什么时候会 error ,什么时候会 complete ,细节是魔鬼,确认过细节后你才能确定代码的执行是符合你的预期的。
比如
a$.pipe(combineLatestWith(b$)).subscribe(v => console.log(v))
,如果a$
next 值了,我们能看到 console 吗?如果b$
也 next 值了,我们能看到 console 吗?如果b$
又 next 值了,我们能看到 console 吗?以及哪些情况会 error ?各种 Subject 我应该怎么选
.value
拿到当前值null
,而业务上是需要等待一个有效值,那么 subscribe 时记得加上filter
来过滤掉无效值)没啥特殊需求就 Subject ;如果希望设置初始值或者希望能直接拿到当前值,那么就用 BehaviorSubject ;如果希望能记录旧值但是不需要设置初始值那就 ReplaySubject ,但是要注意 ReplaySubject 和 Subject 一样不能直接拿到值,只能通过 subscribe 来拿到值。
我现在觉得的最佳实践(也许未来会有不一样想法
a$ = b$.pipe(xxx)
(在 Angular 中 html 也可以直接xxx$ | async
,不用再关心取消订阅了)