1

I'm using Angular 9. I want to load a series of objects, each of which has image data. I would like to load all the objects, first, and then load the image data after. I have this in my component.ts file ngOnInit ...

  ngOnInit(): void {

    this.authService.getAllinLibrary().subscribe((res: any[]) => { 
      this.results = res;
      ...

      for (let i = 0; i < results.length; i++) {
        this.getTheImage(res[i].Id, i);
      }
    });



  getTheImage(imageId: number, index: number) {
    this.authService.getPersonImage(imageId).subscribe(data => {
      this.createImageFromBlob(data, index);
      this.isImageLoadingArr[index] = false;
      console.log("loaded image:" + index);
    }, error => {
      this.isImageLoadingArr[index] = false;
      console.log(error);
    });
  }
  

    I display the data in my component like so

             <mat-grid-tile *ngFor="let person of results; let i = index;" class="animated flipInX">

                  <div class="image-background">
                      <img [src]="images[i]"
                        alt="" width="100%">
                      

It seems that all the calls to load the image data are not being run concurrently. That is, every time, I get the log messages

loaded image: 0
loaded image: 1
loaded image: 2
loaded image: 3
loaded image: 4
     ....
 

printed in sequential orde, leading me to believe the calls aren't getting executed concurrently. How do I modify what I have so that the calls to get the image sources get executed concurrently and not one at a time?

Dave
  • 15,639
  • 133
  • 442
  • 830
  • 1
    Well because of your foreach loop you will call an request multiple times. It's not that each request waits for each other, but the foreach loop results in an tiny difference. If you want to call multiple requests, there's something like `Promise.all` or in `rxjs` `forkJoin()`. Have a look at this blog: https://coryrylan.com/blog/angular-multiple-http-requests-with-rxjs – Tom Nov 10 '20 at 15:09

1 Answers1

0

I think the best appraoch is to implement forkJoin Rxjs specifications :

     this.authService.getAllinLibrary().subscribe((res: any[]) => { 
          this.results = res;
          ...
     let observableBatch = [];

  results .forEach(( componentarray, key ) => {
    observableBatch.push( this.getTheImage(res[key ].Id, key); );
  });
 

      const getImagesObservable= forkJoin(observableBatch );
       
    getImagesObservable.subscribe({
     next: value => your Implementation Here
     complete: () => console.log('This is how it ends!'),
    });

});

Rebai Ahmed
  • 1,509
  • 1
  • 14
  • 21
  • Follow up -- here you are building the array using hard-coded, "this.getTheImage(res[i].Id, i)". If I don't know how many instances I have at compile time, can I just build an array first and then pass that to "const getImagesObservable= forkJoin("? – Dave Nov 10 '20 at 15:58
  • Hi I just edited my answer, you can use a variable observable patch to set your subscriptions calls and pass it as an argument to the fork-join operation , please upvote if it helps you :) – Rebai Ahmed Nov 10 '20 at 16:19
  • Thanks! Last question -- you subscribe to the forkJoin and then process "next" and "complete" values. I'm noticing other sites when there are just "results" processed by the "subscribe" method. Is there any practical difference between the two? – Dave Nov 10 '20 at 17:21