等到所有可观察物完成

时间:2019-07-13 14:02:13

标签: javascript rxjs observable

在我的代码中,几乎没有像这样的可观察对象。

this.server.doRequest().subscribe(response => console.log(response)
      error => console.log(error),
      () => {
        console.log('completed');
      });

此Observable的数量可以是任意数量。 所以我需要编写一个函数来检查每个Observable是否完成,否则请等到每个完成为止。

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

我要在哪里使用它。例如,我有一个页面,用户可以异步上传任何数量的照片,然后按“完成”按钮。他按下“完成”按钮后,我需要等到所有动态创建的Observable都完成。

2 个答案:

答案 0 :(得分:1)

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

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

forkJoin在所有可观察到的可观察值都完成之前不会发出。使其成为等待多个可观察物完成的首选操作员。您还可以向其提供一系列可观察值。还有许多其他运算符也可以满足您的要求,例如concat,merge,combinateLatest或其他一些运算符。

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

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

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

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

<button (click)="finish()">Finish</button>

“添加照片”按钮可获取用户照片及所有图片,完成即是您的完成,您可以拥有这样的组件:

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();
}

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

这是一个展示功能的堆叠闪电战:

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

答案 1 :(得分:0)

我要创建一个字典(在JavaScript中,这将是带有可观察名称的布尔属性的JSON),在其中将每个可观察值推送到“创建”,并在每个可观察值完成时执行一个方法,该方法将遍历该可观察值字典,如果全部完成,则可以执行某些操作。 这将确保并行性和完成后的最终执行。

var requests = {
    doRequest1: false,
    doRequest2: false,
    doRequest3: false
};

var checkIfCAllCompleted = name => {
    requests[name] = true;
    for (var property in requests) {
        if (object.hasOwnProperty(property)) {
            if (!property) {
                return;
            }
        }
    }
    // all properties are true - do something here
    console.log("here");
}
this.server.doRequest1().then(() => checkIfCAllCompleted("doRequest1"));
this.server.doRequest2().then(() => checkIfCAllCompleted("doRequest2"));
this.server.doRequest3().then(() => checkIfCAllCompleted("doRequest3"));
相关问题