Zone.js, Angular'ın uygulama durumunun değişmiş olabileceğini algılamak için kullandığı bir sinyal mekanizmasıdır. setTimeout, ağ istekleri ve olay dinleyicileri gibi asenkron işlemleri yakalar. Angular, Zone.js'den gelen sinyallere dayalı olarak değişiklik algılamasını planlar.
Bazı durumlarda planlanan görevler veya mikro görevler veri modelinde herhangi bir değişiklik yapmaz, bu da değişiklik algılaması çalıştırmayı gereksiz kılar. Yaygın örnekler şunlardır:
requestAnimationFrame,setTimeoutveyasetInterval- Üçüncü taraf kütüphaneleri tarafından görev veya mikro görev planlaması
Bu bölüm, bu tür koşulların nasıl belirleneceğini ve gereksiz değişiklik algılama çağrılarından kaçınmak için kodun Angular zone'unun dışında nasıl çalıştırılacağını kapsamaktadır.
Gereksiz değişiklik algılama çağrılarını belirleme
Gereksiz değişiklik algılama çağrılarını Angular DevTools ile tespit edebilirsiniz. Genellikle profil çıkarıcının zaman çizelgesinde setTimeout, setInterval, requestAnimationFrame veya bir olay işleyicisi kaynaklı ardışık çubuklar olarak görünürler. Bu API'lerin uygulamanız içinde sınırlı çağrıları olduğunda, değişiklik algılama çağrısı genellikle bir üçüncü taraf kütüphanesi tarafından neden olur.

Yukarıdaki görüntüde, bir elemanla ilişkili olay işleyicileri tarafından tetiklenen bir dizi değişiklik algılama çağrısı vardır. Bu, NgZone'un varsayılan davranışını değiştirmeyen üçüncü taraf, yerel olmayan Angular bileşenleri kullanırken yaygın bir zorluktur.
Görevleri NgZone dışında çalıştırma
Bu tür durumlarda, NgZone kullanarak Angular'a belirli bir kod parçası tarafından planlanan görevler için değişiklik algılaması çağırmamasını talimat verebilirsiniz.
Zone dışında çalıştırma
1import { Component, NgZone, OnInit, inject } from '@angular/core';
2
3@Component(...)
4class AppComponent implements OnInit {
5 private ngZone = inject(NgZone);
6
7 ngOnInit() {
8 this.ngZone.runOutsideAngular(() => setInterval(pollForUpdates, 500));
9 }
10}
Önceki kod parçası, Angular'a setInterval'i Angular Zone'unun dışında çağırmasını ve pollForUpdates çalıştıktan sonra değişiklik algılaması çalıştırmayı atlamasını talimat verir.
Üçüncü taraf kütüphaneleri, API'leri Angular zone'u içinde çağrıldığında genellikle gereksiz değişiklik algılama döngülerine neden olur. Bu olgu özellikle olay dinleyicileri ayarlayan veya diğer görevler (zamanlayıcılar, XHR istekleri vb.) başlatan kütüphaneleri etkiler. Kütüphane API'lerini Angular zone'unun dışında çağırarak bu ekstra döngülerden kaçının:
Grafik başlatmayı Zone dışına taşıma
1import { Component, NgZone, OnInit, inject } from '@angular/core';
2import * as Plotly from 'plotly.js-dist-min';
3
4@Component(...)
5class AppComponent implements OnInit {
6 private ngZone = inject(NgZone);
7
8 ngOnInit() {
9 this.ngZone.runOutsideAngular(() => {
10 Plotly.newPlot('chart', data);
11 });
12 }
13}
Plotly.newPlot('chart', data);'yi runOutsideAngular içinde çalıştırmak, framework'a başlatma mantığı tarafından planlanan görevlerin çalıştırılmasından sonra değişiklik algılaması çalıştırmaması gerektiğini bildirir.
Örneğin, Plotly.newPlot('chart', data) bir DOM elemanına olay dinleyicileri eklerse, Angular onların işleyicilerinin çalıştırılmasından sonra değişiklik algılaması çalıştırmaz.
Ancak bazen üçüncü taraf API'leri tarafından gönderilen olayları dinlemeniz gerekebilir. Bu tür durumlarda, başlatma mantığı orada yapıldıysa bu olay dinleyicilerinin de Angular zone'unun dışında çalışacağını hatırlamak önemlidir:
İşleyicinin Zone dışında çağrılıp çağrılmadığını kontrol etme
1import { Component, NgZone, OnInit, output, inject } from '@angular/core';
2import * as Plotly from 'plotly.js-dist-min';
3
4@Component(...)
5class AppComponent implements OnInit {
6 private ngZone = inject(NgZone);
7
8 plotlyClick = output<Plotly.PlotMouseEvent>();
9
10 ngOnInit() {
11 this.ngZone.runOutsideAngular(() => {
12 this.createPlotly();
13 });
14 }
15
16 private async createPlotly() {
17 const plotly = await Plotly.newPlot('chart', data);
18
19 plotly.on('plotly_click', (event: Plotly.PlotMouseEvent) => {
20 // Bu işleyici Angular zone'unun dışında çağrılacaktır çünkü
21 // başlatma mantığı da zone'un dışında çağrılmıştır. Angular
22 // zone'unda olup olmadığımızı kontrol etmek için aşağıdakini çağırabiliriz:
23 console.log(NgZone.isInAngularZone());
24 this.plotlyClick.emit(event);
25 });
26 }
27}
Üst bileşenlere olay göndermeniz ve belirli görünüm güncelleme mantığı çalıştırmanız gerekiyorsa, framework'a değişiklik algılaması çalıştırmasını talimat vermek için Angular zone'una yeniden girmeyi veya değişiklik algılamasını manuel olarak çalıştırmayı düşünmelisiniz:
1import { Component, NgZone, OnInit, output, inject } from '@angular/core';
2import * as Plotly from 'plotly.js-dist-min';
3
4@Component(...)
5class AppComponent implements OnInit {
6 private ngZone = inject(NgZone);
7
8 plotlyClick = output<Plotly.PlotMouseEvent>();
9
10 ngOnInit() {
11 this.ngZone.runOutsideAngular(() => {
12 this.createPlotly();
13 });
14 }
15
16 private async createPlotly() {
17 const plotly = await Plotly.newPlot('chart', data);
18
19 plotly.on('plotly_click', (event: Plotly.PlotMouseEvent) => {
20 this.ngZone.run(() => {
21 this.plotlyClick.emit(event);
22 });
23 });
24 }
25}
Angular zone'unun dışında olay gönderme senaryosu da ortaya çıkabilir. Değişiklik algılamasını tetiklemenin (örneğin, manuel olarak) Angular zone'unun dışında görünümlerin oluşturulmasına/güncellenmesine yol açabileceğini hatırlamak önemlidir.