Что такое NgZone и как он взаимодействует с Change Detection в Angular?
Что проверяют
Понимаете ли вы, откуда Angular узнаёт об изменении данных, и отделяете ли механизм оповещения (Zone.js и NgZone) от самой проверки изменений. Ответ показывает, чинит ли кандидат «представление не обновилось» осознанно или наугад расставляет вызовы detectChanges.
Как отвечать
Zone.js подменяет асинхронные API браузера: таймеры, обработчики событий, запросы, промисы. NgZone это обёртка Angular над такой зоной. Сам он изменения не проверяет, а следит, когда очередь микрозадач опустела, и по этому событию запускает обход дерева компонентов через ApplicationRef.
На практике важны два метода:
this.zone.runOutsideAngular(() => {
requestAnimationFrame(loop); // тяжёлый цикл, сторонняя карта, график
});
this.zone.run(() => { this.progress = value; }); // вернулись в зонуПервый убирает лишние проходы проверки, второй возвращает выполнение обратно. Если данные пришли из кода, о котором Zone.js не знает, представление не обновится само, пока его не подтолкнуть через run, markForCheck или сигнал.
Сильный ответ показывает, куда движется фреймворк: стратегия OnPush сокращает обход до ветки с изменившимися входами, сигналы дают точечное обновление зависимых узлов, а в современных версиях доступен режим без Zone.js, где проверку планируют сами сигналы и события, и NgZone из схемы уходит.
Где спотыкаются
Говорят, что NgZone запускает проверку изменений. Он лишь сообщает о стабилизации очереди задач, а обход дерева делает ApplicationRef, и из этой путаницы растут попытки вызывать run там, где нужен markForCheck.
Меняют состояние внутри runOutsideAngular, а в run заворачивают только логирование. Возвращать в зону надо само присваивание, иначе обновление экрана держится на постороннем событии, которое придёт следом случайно.
Лечат симптом вызовом detectChanges на каждое значение потока и получают ту же нагрузку, от которой уходили. Чаще нужен OnPush вместе с асинхронным пайпом, который ещё и отпишется сам, либо перевод состояния на сигналы.