在我的代码中,几乎没有像这样的可观察对象。
this.server.doRequest().subscribe(response => console.log(response)
error => console.log(error),
() => {
console.log('completed');
});
此Observable的数量可以是任意数量。 所以我需要编写一个函数来检查每个Observable是否完成,否则请等到每个完成为止。
我假设我可以在其中创建每个新的Observable的数组推送,并在完成后按索引将其删除。但这是一个好的解决方案吗?
我要在哪里使用它。例如,我有一个页面,用户可以异步上传任何数量的照片,然后按“完成”按钮。他按下“完成”按钮后,我需要等到所有动态创建的Observable都完成。
答案 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();
}
如果运行此代码,您会看到添加的照片将在完成时在订阅处理程序中发出,但是只有在所有照片上传完成并且用户单击完成后才会触发完成。
这是一个展示功能的堆叠闪电战:
答案 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"));