Angular中如何将多个Observer值作为方法参数传递
回答
完全可以实现,不需要手动为每个字段维护冗余的组件属性,借助RxJS原生提供的组合操作符就能达到和模板async管道一致的取值效果。
首先说明你原写法的问题:subscribe()执行后返回的是Subscription订阅实例,并不是Observable输出的实际值,所以直接把调用结果作为参数传入接口方法必然无法正常运行。
常用实现方案
根据你的业务场景选对应写法即可:
场景1:触发时取一次最新值提交(绝大多数业务场景)
如果是点击提交按钮、触发特定逻辑时,仅需要拿一次当前最新的用户信息调用接口,用forkJoin搭配take(1)实现即可,写法最简洁:
import { forkJoin, take, switchMap } from 'rxjs'; // 组合三个用户信息Observable,取一次最新值后调用接口 forkJoin({ fullName: this.userObserver.getFullName().pipe(take(1)), phone: this.userObserver.getPhoneNumber().pipe(take(1)), email: this.userObserver.getEmailAddress().pipe(take(1)) }).pipe( switchMap(userInfo => this.httpService.createSomething( userInfo.fullName, userInfo.phone, userInfo.email )) ).subscribe(() => console.log('Well done'));
这里加take(1)是为了兼容不会自动完成的流(比如用BehaviorSubject存储的全局用户信息流,本身不会触发complete事件),取到一次值后会自动取消对上游用户流的订阅,不会造成内存泄漏。
场景2:跟随数据变化自动触发接口
如果你需要任意一个用户字段更新时,都自动用最新值重新调用createSomething接口,把forkJoin换成combineLatest即可:
import { combineLatest, switchMap } from 'rxjs'; combineLatest([ this.userObserver.getFullName(), this.userObserver.getPhoneNumber(), this.userObserver.getEmailAddress() ]).pipe( switchMap(([fullName, phone, email]) => this.httpService.createSomething(fullName, phone, email)) ).subscribe(() => console.log('Well done'));
注意:
combineLatest会等待所有输入流至少吐出过一个值后才开始发射组合结果,后续任意一个流推送新值都会重新执行后续接口逻辑,记得在组件ngOnDestroy生命周期中取消这个订阅,避免内存泄漏。
原理说明
Angular的async管道底层本质就是「订阅Observable、读取最新值、组件销毁时自动取消订阅」这一套逻辑,上面的写法只是把模板里管道帮你做的事移到了TS代码中实现,完全不需要手动写三次订阅、给三个组件属性重复赋值,代码可维护性高很多。
内容的提问来源于stack exchange,提问作者Ste
相关产品推荐
相关产品推荐

