如何多次订阅 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 文件中的 onInitonDestroy

就是这样!当 reloadUsersData() 被调用时,它会导致 fetchEvent 发出一个新值。因为 users$ 有一个活跃的订阅,它会收到那个新值,并再次订阅内部 switchMap observable。

注意: switchMapTo(obs$) 运算符类似于 switchMap((value)=>$obs) 运算符。只是代码少了一点,因为我们实际上并不需要 BehaviorSubject.

中的值