如何多次订阅 observable?
How to subscribe to observable multiple times?
我有一个 table 每次用户删除一行或使用名为 reloadUsersData() 的指定函数编辑数据时都需要刷新;
我创建了一个从服务获取 table 数据的 BehaviorSubject - 一旦 table 被加载 - 但我不确定我的 reloadUsersData 实现是否良好,因为我重复了相同的代码并重新订阅相同的可观察对象....
export class TableBasicExample implements OnDestroy, OnInit{
dataSource$ = new BehaviorSubject<any>([]);
private subs: Subscription[] = [];
constructor(private apiService: ApiService) {}
ngOnInit() {
this.subs.push(
this.apiService.getUsers().subscribe((res: any) => {
this.dataSource$.next(res);
}));
}
reloadUsersData(){
// how can i subscribe to the same api more effectively ?
this.subs.push(
this.apiService.getUsers().subscribe((res: any) => {
this.dataSource$.next(res);
}));
}
ngOnDestroy(): void {
this.subs.forEach((us) => us.unsubscribe());
}
}
幸运的是,这可以简化!我假设 .getUsers()
发出一组用户并完成。考虑到这一点,您创建一个主题来处理重新加载事件的想法是正确的。
您可以在 RxJS 中使用的一种策略是创建一个在其 .pipe()
中包含主题的可观察对象。这是因为 Subject
继承了 Observable
.
的所有功能
这是代码。
export class TableBasicExample {
private fetchEvent = new BehaviorSubject<'fetch'>('fetch');
public users$: Observable<User[]>;
constructor(private apiService: ApiService) {
this.users$ = this.fetchEvent.pipe(
switchMapTo(this.apiService.getUsers())
);
}
reloadUsersData() {
this.fetchEvent.next('fetch');
}
}
我们创建一个 BehaviorSubject
(它是 Subject
的扩展)来处理我们的获取事件。我们让它发出字符串 'fetch'
,但实际上它可以是任何值。
接下来,我们声明用于 table 渲染的主要 Observable
。它将订阅 fetchEvent
并将 switchMap
订阅到内部可观察对象 (.getUsers()
) 并发出其值。
最后,我们有 public 方法,它将在我们的私有 BehaviorSubject
中发出一个新值。
在组件的模板文件中,您可以使用 async
管道订阅此可观察对象。
<table *ngIf="users$ | async as users">
<tr *ngFor="user of users">
<!-- table row data -->
</tr>
</table>
<button (click)="reloadUsersData()">Reload</button>
async
管道为您处理 subscribe/unsubscribe 事件,因此您不再需要组件的 TS 文件中的 onInit
和 onDestroy
。
就是这样!当 reloadUsersData()
被调用时,它会导致 fetchEvent
发出一个新值。因为 users$
有一个活跃的订阅,它会收到那个新值,并再次订阅内部 switchMap
observable。
注意: switchMapTo(obs$)
运算符类似于 switchMap((value)=>$obs)
运算符。只是代码少了一点,因为我们实际上并不需要 BehaviorSubject
.
中的值
我有一个 table 每次用户删除一行或使用名为 reloadUsersData() 的指定函数编辑数据时都需要刷新; 我创建了一个从服务获取 table 数据的 BehaviorSubject - 一旦 table 被加载 - 但我不确定我的 reloadUsersData 实现是否良好,因为我重复了相同的代码并重新订阅相同的可观察对象....
export class TableBasicExample implements OnDestroy, OnInit{
dataSource$ = new BehaviorSubject<any>([]);
private subs: Subscription[] = [];
constructor(private apiService: ApiService) {}
ngOnInit() {
this.subs.push(
this.apiService.getUsers().subscribe((res: any) => {
this.dataSource$.next(res);
}));
}
reloadUsersData(){
// how can i subscribe to the same api more effectively ?
this.subs.push(
this.apiService.getUsers().subscribe((res: any) => {
this.dataSource$.next(res);
}));
}
ngOnDestroy(): void {
this.subs.forEach((us) => us.unsubscribe());
}
}
幸运的是,这可以简化!我假设 .getUsers()
发出一组用户并完成。考虑到这一点,您创建一个主题来处理重新加载事件的想法是正确的。
您可以在 RxJS 中使用的一种策略是创建一个在其 .pipe()
中包含主题的可观察对象。这是因为 Subject
继承了 Observable
.
这是代码。
export class TableBasicExample {
private fetchEvent = new BehaviorSubject<'fetch'>('fetch');
public users$: Observable<User[]>;
constructor(private apiService: ApiService) {
this.users$ = this.fetchEvent.pipe(
switchMapTo(this.apiService.getUsers())
);
}
reloadUsersData() {
this.fetchEvent.next('fetch');
}
}
我们创建一个 BehaviorSubject
(它是 Subject
的扩展)来处理我们的获取事件。我们让它发出字符串 'fetch'
,但实际上它可以是任何值。
接下来,我们声明用于 table 渲染的主要 Observable
。它将订阅 fetchEvent
并将 switchMap
订阅到内部可观察对象 (.getUsers()
) 并发出其值。
最后,我们有 public 方法,它将在我们的私有 BehaviorSubject
中发出一个新值。
在组件的模板文件中,您可以使用 async
管道订阅此可观察对象。
<table *ngIf="users$ | async as users">
<tr *ngFor="user of users">
<!-- table row data -->
</tr>
</table>
<button (click)="reloadUsersData()">Reload</button>
async
管道为您处理 subscribe/unsubscribe 事件,因此您不再需要组件的 TS 文件中的 onInit
和 onDestroy
。
就是这样!当 reloadUsersData()
被调用时,它会导致 fetchEvent
发出一个新值。因为 users$
有一个活跃的订阅,它会收到那个新值,并再次订阅内部 switchMap
observable。
注意: switchMapTo(obs$)
运算符类似于 switchMap((value)=>$obs)
运算符。只是代码少了一点,因为我们实际上并不需要 BehaviorSubject
.