Wait for observable in for loop to finish before continuing loop in Angular 5

為{幸葍}努か 提交于 2021-01-27 19:21:58

问题


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 completes. 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);
            });
})

回答1:


If you want to run one Observable at the time and only start the next one after the previous one completed 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.com/zocuma/3/edit?js,console




回答2:


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


来源:https://stackoverflow.com/questions/48593611/wait-for-observable-in-for-loop-to-finish-before-continuing-loop-in-angular-5

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!