naoval
naoval

Reputation: 368

Angular component when load data from server is blank for a couple seconds

I'm building an angular apps with api calls using httpclient, i don't use any package or plugin for that just httpclient.

Here's my example code in service.ts

  getAdminMateriDetail(slug: any) {
    return this._http.get(this.apiURL + 'admin/material/' + slug).pipe(
      tap(console.log),
      shareReplay(1),
      tap(() => console.log('Materi Detail after sharing'))
    )
  }

i try to get materi detail from server, and in my component

getCurrentMateriDetail() {
    return this.userService.getAdminMateriDetail(this.slug).subscribe(
      (data:any) => {
        this.currentMateri = data.data;
      },
      error => {
        console.log(error);
      }
    )
  }

  ngOnInit() {
    this.getCurrentMateriDetail();
  }

i use that code in every page that needs data from server, but what i get is unexpected result, so when i navigate to component that calls an api and subscribe to that api, my component was blank for a couple seconds, sometime it's fast. I'm new using api calls, so is it normal? or maybe i can improve it to make it fast so user won't see a "blank page"?

I also read about caching, and i found shareReplay(1) so i add it to my code but still blank for a couple of second. can someone give me the reason?

Upvotes: 0

Views: 924

Answers (2)

izmaylovdev
izmaylovdev

Reputation: 1880

API calls always takes time. So you need to create loader or something like that. In component template you can do it with ngIfElse:

<ng-container *ngIf="loadedData; else loader">
  page content
</ng-container>

<ng-template #loader>Loading...</loader>

shareReplay used for share result of "cold" (more info) observable between subscribers. But in your case it's useless, because every call of your function creates new Observable. Example:

// Correct usage: 
const myMagicData$ = this._http.get(this.apiURL + 'admin/material/' + slug).pipe(
      tap(console.log),
      shareReplay(1),
      tap(() => console.log('Materi Detail after sharing'))
    );
    
myMagicData$.subscribe();
myMagicData$.subscribe();

In example above both subscriptions got same result. Without shareReplay() every subscription triggers API call.

Upvotes: 1

Random
Random

Reputation: 3236

This is expected behavior, since you are doing an async call:

this.userService.getAdminMateriDetail(this.slug).subscribe(
  (data:any) => {
    this.currentMateri = data.data;
  },
  error => {
    console.log(error);
  }
)

Here, this.currentMateri is null until the server responds (assume it to be between 0.1sec and 1 second). So in your HTML, you have to handle "what to do when this.currentMateri is null ?"

To handle this, add *ngIf="currentMateri" where you display asynchronous data, and add an other tag (div, or whatever) when *ngIf="!currentMateri", so you will display a loader, or anything...

Upvotes: 1

Related Questions