等待所有 Observables 完成

Nic*_*ckD 3 javascript observable rxjs

我的代码中很少有像这样的 Observables。

this.server.doRequest().subscribe(response => console.log(response)
      error => console.log(error),
      () => {
        console.log('completed');
      });
Run Code Online (Sandbox Code Playgroud)

这些 Observable 可能有任意数量,因此我需要编写一个函数来检查每个 Observable 是否已完成,否则将等待每个 Observable 完成。

我假设我可以创建一个数组,将每个新的 Observable 推送到那里,并在完成后按索引将其删除。但这是好的解决方案吗?

我想在哪里使用它。例如,我有一个页面,用户可以异步上传任意数量的照片,然后按“完成”按钮。一旦他按下“完成”按钮,我需要等待所有动态创建的可观察对象完成。

bry*_*n60 5

您应该为此使用更高阶的可观察量,您的确切用例将决定确切的运算符,但 forkJoin 似乎是一个不错的选择:

forkJoin(
  this.server.doRequest1(),
  this.server.doRequest2(),
  this.server.doRequest3(),
  this.server.doRequest4()
).subscribe(vals => console.log('all values', vals));
Run Code Online (Sandbox Code Playgroud)

在所有内部可观察对象完成之前,forkJoin 不会发出。使其成为等待多个可观察对象完成的首选运算符。您还可以向其提供一系列可观察值。还有多个其他运算符也可以满足您的情况,例如 concat、merge、combineLatest 或其他一些运算符。

根据更多详细信息进行编辑:

在更新中描述的用例中,您仍然希望使用更高阶的可观察量,但 forkjoin 不是您想要的。你会想要使用本地主题来实现目标,因为想要在选择每个可观察对象时启动它并等待它们全部完成会使事情变得有点复杂(但不会太多):

假设您有一个类似的模板:

<button (click)="addPhoto()">Add Photo</button>

<button (click)="finish()">Finish</button>
Run Code Online (Sandbox Code Playgroud)

其中“添加照片”按钮获取用户照片等,完成是您的完成,您可以拥有如下组件:

private addPhoto$ = new Subject();

constructor() {
  this.addPhoto$.pipe(
    mergeMap(() => this.uploadPhoto()),
  ).subscribe(
    (resp) => console.log('resp', resp),
    (err) => console.log('err', err),
    () => console.log('complete')
  );
}

private uploadPhoto() {
  // stub to simulate upload
  return timer(3000);
}

addPhoto() {
  this.addPhoto$.next();
}

finish() {
  this.addPhoto$.complete();
}
Run Code Online (Sandbox Code Playgroud)

如果运行此代码,您将看到照片添加将在完成时在订阅处理程序中发出,但只有在所有照片上传完成并且用户单击“完成”后才会触发“完成”。

这是一个 stackblitz 演示的功能:

https://stackblitz.com/edit/angular-bsn6pz