Home > Blockchain >  How to loop through images in angular while images are delivered from API?
How to loop through images in angular while images are delivered from API?

Time:05-26

I have a list of items in my database. Each item has some entities and one of them is ImageFileName. This ImageFileName represents the file and its extension. I want to loop through the database and render all the images along with their other entities. The Html is:

<div  *ngFor="let post of specialPosts">
    <div >
      <img [src]="GetImage(post.imageFileName)"  [alt]="post.title" />
</div>

The component related to this Html is:

export class SpecialPostComponent implements OnInit {

  constructor(private postService: PostService) { }

  specialPosts: Post[] = [];

  ngOnInit(): void {
    this.GetSpecialPost();
  }

  GetSpecialPost() {
    this.postService.GetSpecialPost().subscribe(
      response => {
        this.specialPosts = response;
        // console.log(response);
      }
    );
  }
  CreateImageFromBlob(image: Blob) {
    let reader = new FileReader();
    if (image != null) {
      reader.readAsDataURL(image);
      reader.addEventListener("load", () => {
        return = reader.result;
      }, false);
    }
  }
  GetImage(filename: string) {
    this.postService.GetSpecialPostImage(filename).subscribe(
      response => this.CreateImageFromBlob(response)
    );
  }
}

The service used for connecting to API is:

export class PostService {

  constructor(private http: HttpClient) {

   }
   GetSpecialPost(): Observable<Post[]>{
     return this.http.get<Post[]>(url.baseURL   '/posts/getspecialpostslist');
   } 
   }
   GetSpecialPostImage(filename: string): Observable<Blob>{
    return this.http.get(url.baseURL   '/posts/getspecialpostimage?filename='   filename, {"responseType": "blob"});
  }
}

The model:

export interface Post{
    id: number,
    title: string,
    description: string,
    creationDate: string,
    isSpecialPost: boolean,
    isMainPost: Boolean,
    isActive: boolean,
    imageFileName: string,
    name: string
}

The problem is that when I build the project, CPU usage reaches 87% and the browser gets unresponsive and no images are delivered to the browser. How can I loop through images while the images come from API?

Update 1: I changed component code to this:

export class SpecialPostComponent implements OnInit {

  constructor(private postService: PostService) { }

  specialPosts: Post[] = [];
  ImageToShow: any;

  ngOnInit(): void {
    this.GetSpecialPost();
  }

  GetSpecialPost() {
    this.postService.GetSpecialPost().subscribe(
      response => {
        this.specialPosts = response;
        this.PrepareImages(this.specialPosts);
        // console.log(response);
      }
    );
  }
  PrepareImages(post: Post[]){
    post.forEach(element => {
      this.ImageToShow = this.GetImage(element.imageFileName);
    });
  }
  CreateImageFromBlob(image: Blob) {
    let reader = new FileReader();
    if (image != null) {
      reader.readAsDataURL(image);
      reader.addEventListener("load", () => {
        return reader.result;
      }, false);
    }
  }
  GetImage(filename: string) {
    this.postService.GetSpecialPostImage(filename).subscribe(
      response => this.CreateImageFromBlob(response)
    );
  }
}

But, images are not shown.

CodePudding user response:

My suggestion is to prepare images after you get specialPosts and then pass specialPosts with the correct image src to HTML.

import { forkJoin } from 'rxjs';
.
.

  GetSpecialPost() {
    this.postService.GetSpecialPost().subscribe(
      response => {
        this.specialPosts = response;
        this.prepareImages(this.specialPosts);
      }
    );
  }
  
  CreateImageFromBlob(image: Blob): Promise<any> {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.addEventListener('load', () => {
        resolve(reader.result);
      }, false);

      if (image) {
        reader.readAsDataURL(image);
      } else {
        reject();
      }
    });
  }

  prepareImages(posts: Post[]) {
    forkJoin(
      posts.map(post =>
         this.postService.GetSpecialPostImage(post.filename).pipe(
          mergeMap(async (response: Blob) => {
            post.imageSrc = await this.CreateImageFromBlob(response);
            return post;
          }))
      )
    ).subscribe((posts: Post[]) => {
      this.reviseSpecialPosts = [...posts];
    });
  }

And in the HTML you just need to pass imageSrc:

<div  *ngFor="let post of reviseSpecialPosts">
    <div >
      <img [src]="post?.imageSrc"  [alt]="post.title" />
    </div>
</div>
  • Related