admin管理员组文章数量:1327684
I'm looping through an array of objects (called projects). The forEach loop contains a service call that returns an observable. I'm trying to wait to process the next project in the array until the observable within the loop pletes. What should I use? I tried forkJoin already.
projects
.forEach(project => {
this.imageService.getProjectImages(project.projectId.toString(), true, true, undefined)
.catch(err => observer.error(err))
.finally(() => {
// process next project
})
.subscribe((image: FileRepresentation) => {
data.image = image;
this.getSlide(project, data);
});
})
I'm looping through an array of objects (called projects). The forEach loop contains a service call that returns an observable. I'm trying to wait to process the next project in the array until the observable within the loop pletes. What should I use? I tried forkJoin already.
projects
.forEach(project => {
this.imageService.getProjectImages(project.projectId.toString(), true, true, undefined)
.catch(err => observer.error(err))
.finally(() => {
// process next project
})
.subscribe((image: FileRepresentation) => {
data.image = image;
this.getSlide(project, data);
});
})
Share
edited Feb 3, 2018 at 5:53
depiction
asked Feb 3, 2018 at 3:21
depictiondepiction
8198 silver badges17 bronze badges
3
- 2 show the tried forkjoin – Sachila Ranawaka Commented Feb 3, 2018 at 3:31
- forkJoin only works for an array of observables. I have an array of objects. – depiction Commented Feb 3, 2018 at 5:56
-
1
use
map
:projects.map(project => this.imageService.getProjectImages(project.projectId.ToString()...))
will return array of observables. – Harry Ninh Commented Feb 3, 2018 at 6:27
2 Answers
Reset to default 5If you want to run one Observable at the time and only start the next one after the previous one pleted then forkJoin
is not a good choice because it subscribes to all source Observables right away. A better approach is using so called higher-order Observable and subscribe to one after another with concatAll
:
const projects = [
Observable.of(1).delay(1000),
Observable.of(2).delay(1000),
Observable.of(3).delay(1000),
];
Observable.from(projects)
.concatAll()
.subscribe(console.log);
This simulates the HTTP call by making an Observable with 1s delay. If you run this example you'll see that it prints each number with 1s delay:
See live demo: http://jsbin./zocuma/3/edit?js,console
I eventually figured out a solution. The key is to use a second function that is called recursively.
Pass all projects and the first project's index to getImagesForProject. Once all images have been received for the first project, check to see if the imageCount is less than maxImages. If yes, call getImagesForProject recursively until the limit is reached.
this.getImagesForProject(projects, 0, 5);
getImagesForProject(projects: Project[], index: number, maxImages: number = 5, imageCount?: number) {
this.imageService.getProjectImages(projects[index].projectId.toString(), true, true, undefined)
.finally(() => {
if(imageCount < maxImages) {
this.getImagesForProject(projects, data, (index + 1), imageCount);
}
})
.subscribe(image => {
imageCount++;
data.image = image;
this.getSlide(projects[index], data);
});
}
版权声明:本文标题:javascript - Wait for observable in for loop to finish before continuing loop in Angular 5 - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742221112a2435448.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论