Внести вклад
Энциклопедия ошибок

Приложение остается нестабильным

Это предупреждение появляется только в браузере в процессе гидратации, когда она включена на клиенте, но приложение остается нестабильным в течение длительного времени (более 10 секунд).

Обычно это происходит, когда на странице есть незавершенные микрозадачи (microtasks) или макрозадачи (macrotasks).

Гидратация Angular полагается на сигнал от ApplicationRef.isStable, когда приложение становится стабильным:

  • во время рендеринга на стороне сервера (SSR) для запуска процесса сериализации;
  • в браузере этот сигнал используется для запуска очистки после гидратации, чтобы удалить DOM-узлы, которые остались невостребованными.

Это предупреждение отображается, если ApplicationRef.isStable не выдает значение true в течение 10 секунд. Если это поведение является намеренным и ваше приложение стабилизируется позже, вы можете игнорировать это предупреждение.

Приложения, использующие zone.js

Приложения, использующие zone.js, могут сталкиваться с различными факторами, вызывающими задержку стабилизации. К ним относятся незавершенные HTTP-запросы, таймеры (setInterval, setTimeout) или логика, которая непрерывно вызывает requestAnimationFrame.

Макрозадачи (Macrotasks)

Макрозадачи включают такие функции, как setInterval, setTimeout, requestAnimationFrame и другие. Если одна из этих функций вызывается на этапе инициализации приложения или в загружаемых компонентах, это может отсрочить момент, когда приложение станет стабильным.

@Component({
  selector: 'app',
  template: ``,
})
class SimpleComponent {
  constructor() {
    setInterval(() => { ... }, 1000)

    // или

    setTimeout(() => { ... }, 10_000)
  }
}

Если вызов этих функций необходим на этапе инициализации, их запуск вне зоны Angular решает проблему:

class SimpleComponent {
  constructor() {
    const ngZone = inject(NgZone);

    ngZone.runOutsideAngular(() => {
      setInterval(() => {}, 1000);
    });
  }
}

Сторонние библиотеки

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

Запуск кода после стабилизации приложения

Вы можете запустить код, устанавливающий асинхронные задачи, как только приложение станет стабильным:

class SimpleComponent {
  constructor() {
    const applicationRef = inject(ApplicationRef);

    applicationRef.isStable.pipe( first((isStable) => isStable) ).subscribe(() => {
      // Обратите внимание, что нам не нужно использовать `runOutsideAngular`,
      // так как `isStable` выдает события вне зоны Angular, когда значение истинно
      // (ложные значения выдаются внутри зоны Angular).
      setTimeout(() => { ... });
    });
  }
}

Zoneless-приложения

В сценариях без использования зон (zoneless), стабилизация может задерживаться кодом приложения внутри effect, работающим в бесконечном цикле (возможно, потому что сигналы, используемые в функциях эффекта, постоянно меняются), или незавершенным HTTP-запросом.

Разработчики также могут явно влиять на индикацию стабильности приложения, используя сервис PendingTasks. Если вы используете упомянутые API в своем приложении, убедитесь, что вы вызываете функцию для отметки задачи как выполненной.