Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

http.get too slow, change detection not registering changes

I am building a calendar-app that uses http.get to get information for a certain day from the backend (currently backend is a server-mock). My issue is that the asynchronous http.get is not fast enough to deliver the data during the page rendering and somehow the data does not get displayed once it arrived either, I believe change detection should pick this up normally. Regarding the http.get method I followed the example on Angular.io, found here https://angular.io/guide/http#subscribe

To the code:

FetchService:

getDayInfo(date: string): Observable<any> {
  return this.http.get(url)
    .map(this.extractData)
    .catch(this.handleError);
}

private extractData(res: Response) {
  let body = res.json();
  return body; // not really doing much with the data here yet
}

component.ts:

dayData: any[];
dayInfo: any[];

constructor(private fetcher: FetchService) {}

ngOnInit(): void {
  this.getDay();
  setTimeout(() => { this.setDayData(); }, 10); 
  // the setTimeout is mostly here for testing, tried to sort of set the
  // Data after the async http.get was done
}  

getDay () {
  this.fetcher.getDayInfo(this.date).subscribe(
    body => this.dayInfo = body,
  );
}

setDayData() {
  if (this.dayInfo) {
    this.dayData = this.dayInfo;
    console.log(this.dayData);
    // and some more things that only matter for some CSS markup
  }
}

component.html:

<!--{{ dayInfo[0].type.name }}-->
<div *ngIf="dayData">
  <div *ngFor="let data of dayData">
    <p>{{ data.type.name }}</p>
  </div>
</div>
<div *ngIf="!dayData">
  <p>Loading</p>
</div>

Every day always just shows Loading, after the Timeout, the console fills with actual and proper dayData, site still only shows Loading. If I comment in the {{ dayInfo[0].type.name }} in the html, I first get a few days with "Loading" and a console with errors saying dayInfo is undefined, then bit by bit, the days fill, showing Loading and the data I want, though the console is full of errors as stated above.

Now, since I can't speed up the asynchronous http.get, is there a way to trigger the change detection to pick up the change in dayData? Or any other work-around for me to display the proper Data?

PS: another thing I noticed when console-logging the dayData in setDayData is that sometimes the log doesn't list all days, meaning it may show the first 27 days of a month, but have no log entry regarding the rest. Not sure what causes this.


Edit: After the first comment and first answer, I changed my getDay method in the component.ts to:

getDay () {
  this.fetcher.getDayInfo(this.date).subscribe(
    body => {
      this.dayInfo = body;
      this.setDayData();
  );
}

Now the odd behavior I described in "PS:" above, is gone, all days are showing in the log, though they are mixed around (not in chronological order anymore). Site still only shows "Loading" though and does not update to the proper data. I would likely need to manually trigger change detection here or something.

like image 946
m41n Avatar asked Nov 26 '25 23:11

m41n


1 Answers

Your timeout may be firing before you get your data. Instead of calling the setDayData from your ngOnInit, you probably want to call it from the body of your getDayInfo subscribe block.

This will make sure you have the data and your follow up methods are called after you receive the data.

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

getDay () {
  this.fetcher.getDayInfo(this.date).subscribe(
    body => {
        this.dayInfo = body;
        this.setDatData();
    }
  );
}

As for the other problem about getting undefined - that is because you have an empty array when the template is first displayed (it's not set until your setDayData method is run). You can wrap that in an ngIf too if you actually want that on screen. That way you know you have data there as well.

like image 95
William Jones Avatar answered Nov 29 '25 17:11

William Jones