angulartypescript

Angular V18 PM [vite] Internal server error: Page /home did not render in 30 seconds


In my Angular project (v18) I am receiving the following error:

9:20:15 PM [vite] Internal server error: Page /home did not render in 30 seconds.
      at Timeout.<anonymous> (/Users/jan/Projekts/PflanzenApp/node_modules/@angular/build/src/utils/server-rendering/render-page.js:90:90)
      at Timeout.timer (/Users/jan/Projekts/PflanzenApp/node_modules/zone.js/fesm2015/zone-node.js:2198:37)
      at _ZoneDelegate.invokeTask (/Users/jan/Projekts/PflanzenApp/node_modules/zone.js/fesm2015/zone-node.js:398:33)
      at _ZoneImpl.runTask (/Users/jan/Projekts/PflanzenApp/node_modules/zone.js/fesm2015/zone-node.js:158:47)
      at invokeTask (/Users/jan/Projekts/PflanzenApp/node_modules/zone.js/fesm2015/zone-node.js:479:34)
      at Timeout.ZoneTask.invoke (/Users/jan/Projekts/PflanzenApp/node_modules/zone.js/fesm2015/zone-node.js:468:48)
      at Timeout.data.args.<computed> (/Users/jan/Projekts/PflanzenApp/node_modules/zone.js/fesm2015/zone-node.js:2180:32)
      at listOnTimeout (node:internal/timers:573:17)
      at process.processTimers (node:internal/timers:514:7)

There is no logical reason why this happens because aside from the error message everything works perfectly fine and just as it should.

This seems to be the error producing code snippet

import { Component, OnInit } from '@angular/core';
import { Location } from '@angular/common';
import { Router, RouterLink } from '@angular/router';
import { QuoteComponent } from '../quote/quote.component';
import { WeatherDisplayComponent } from '../weather-display/weather-display.component';
import { Plant } from '../classes/plants';
import { PlantService } from '../services/plant.service';
import { CommonModule } from '@angular/common';
import { NgIf } from '@angular/common';

@Component({
  selector: 'app-home-page',
  standalone: true,
  imports: [QuoteComponent, RouterLink, WeatherDisplayComponent, CommonModule, NgIf],
  templateUrl: './home-page.component.html',
  styleUrl: './home-page.component.css'
})

export class HomePageComponent implements OnInit {
  plants: Plant[] = [];
  pinnedPlants: Plant[] = [];


  days = 0;
  hours = 0;
  minutes = 0;
  seconds = 0;
  waterAmount = 0;

  constructor(private plantService: PlantService) {
    this.plants = plantService.getOwnedPlants();
  }

  ngOnInit(): void {
    this.plants = this.plantService.getOwnedPlants();
    this.pinnedPlants = this.plants.filter(plant => plant.pinned);
    this.pinnedPlants.forEach(plant => this.updatePinnedPlant(plant));
    setInterval(() => this.checkWatering(), 1000);
  }

  daysIntoYear(date: Date): number {
    return (Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()) - Date.UTC(date.getFullYear(), 0, 0)) / 24 / 60 / 60 / 1000;
  }

  updatePinnedPlant(plant: Plant): void {
    const currentTime = new Date();
    plant.waterTime = new Date(currentTime.getTime() + plant.timeBetweenSessions * 60 * 1000); 
  }

  checkWatering(): void {
    const currentTime = new Date();
    this.pinnedPlants.forEach(plant => {
      let timeTillWater = plant.waterTime.getTime() - currentTime.getTime();
       this.days = Math.floor(timeTillWater / (24 * 60 * 60 * 1000));
       this.hours = Math.floor((timeTillWater % (24 * 60 * 60 * 1000)) / (60 * 60 * 1000));
       this.minutes = Math.floor((timeTillWater % (60 * 60 * 1000)) / (60 * 1000));
       this.seconds = Math.floor((timeTillWater % (60 * 1000)) / 1000);

      let multiplier = 1;
      switch (plant.maintenance) {
        case 'Monthly':
          multiplier = 30;
          break;
        case 'Weekly':
          multiplier = 7;
          break;
        case 'Medium':
        case 'Daily':
        default:
          multiplier = 1;
      }

      this.waterAmount = plant.water * multiplier;

      if (timeTillWater <= 0) {
        console.log("Gießen")   
      }     
    });
  }
}

Error appears in the home-page.component.ts file (https://github.com/jamakr4/PflanzenApp)

I have never seen anything like this before and after doing some research I was not able to find anything like this.

The error appears in random intervals sometimes twice per minute, sometimes every 2 seconds.

Any ideas why this happens?


Solution

  • I think the issue is that when initializing the app, it never gets stable. So after 30 seconds, Angular desists of waiting for stability.

    When an Angular app bootstraps, it requires to be stable in order to consider it bootstrapped. Stable means no remaining tasks to perform. Due to the setInterval, there will always be a pending task, hence it will never be stable and won't ever be considered bootstrapped, hence the error.

    This is because Zone.js patches APIs like setInterval therefore it knows when there are pending tasks

    In order to start the setInterval that makes the app permanently unstable, you can do so after the app is stable / bootstrap process finishes:

    @Component({
     //...
    )
    
    export class HomePageComponent implements OnInit {
      constructor(
        private plantService: PlantService,
        private applicationRef: ApplicationRef,
      ) {
        // ...
      }
    
      ngOnInit(): void {
        // ...
        this.applicationRef.isStable.pipe(first((isStable) => isStable)).subscribe(() => {
          setInterval(() => this.checkWatering(), 1000);
        });
      }
    }
    

    As explained in docs about running code after an app becomes unstable