Почему в Angular 9 мои подписки загружаются последовательно, а не параллельно?

#angular #ngfor #subscription

#angular #ngfor #подписка

Вопрос:

Я использую Angular 9. Я хочу загрузить серию объектов, каждый из которых содержит данные изображения. Сначала я хотел бы загрузить все объекты, а затем загрузить данные изображения. У меня есть это в моем файле component.ts 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);
    });
  }
  
  

Я отображаю данные в своем компоненте следующим образом

              <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%">
                      
  

Кажется, что все вызовы для загрузки данных изображения не выполняются одновременно. То есть каждый раз я получаю сообщения журнала

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

печатается в последовательном порядке, что наводит меня на мысль, что вызовы не выполняются одновременно. Как мне изменить то, что у меня есть, чтобы вызовы для получения источников изображений выполнялись одновременно, а не по одному за раз?

Комментарии:

1.Ну, из-за вашего цикла foreach вы будете вызывать запрос несколько раз. Дело не в том, что каждый запрос ожидает друг друга, но цикл foreach приводит к крошечной разнице. Если вы хотите вызвать несколько запросов, есть что-то вроде Promise.all или в rxjs forkJoin() . Взгляните на этот блог: coryrylan.com/blog/angular-multiple-http-requests-with-rxjs

Ответ №1:

Я думаю, что лучшая оценка — реализовать спецификации forkJoin Rxjs :

      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!'),
    });
  

});

Комментарии:

1. Продолжение — здесь вы создаете массив, используя жестко запрограммированный «this.getTheImage(res[i] . Идентификатор, i) «. Если я не знаю, сколько экземпляров у меня есть во время компиляции, могу ли я сначала просто создать массив, а затем передать его в «const getImagesObservable= forkJoin(«?

2. Привет, я только что отредактировал свой ответ, вы можете использовать переменный observable patch для настройки ваших вызовов subscriptions и передать его в качестве аргумента операции fork-join , пожалуйста, поддержите, если это вам поможет 🙂

3. Спасибо! Последний вопрос — вы подписываетесь на forkJoin, а затем обрабатываете значения «next» и «complete». Я замечаю другие сайты, когда есть только «результаты», обработанные методом «subscribe». Есть ли какая-либо практическая разница между ними?