Neden Angular Şablonlarında Metot Kullanmamalıyız?

Tahir KARDAK
4 min readFeb 14, 2021

Merhaba bu yazımda, Angular şablonlarında metot kullanımın performansa etkisi hakkında bilgi vermeye çalışacağım.

Bu yazıyı Ng Turkey ekibinden Mehmet Erim’in yapmış olduğu Angular Zor Değil: Syntax canlı yayınını izledikten sonra yazmaya karar verdim. Sunum sırasında Mehmet Erim’in “Interpolation işlemlerinde metot çağrısının tercih edilmemesi” yönünde bir önerisi olmuştu. Sunum sonunda sorulan aynı soruya gerekli açıklamayı da yapmıştı. Bir örnekle Mehmet’in cevabını göstermek istedim.

Sorunun cevabını en başta vereyim . Angular şablonlarında metot çağrıları yapmak, büyük projelerde performans sorununa yol açabilir.

Şablonlar; Angular’ın en güçlü özelliklerinden biridir. Sunmuş olduğu built-in fonksiyonlar sayesinde DOM’daki işlemleri kolayca yapabilmeye olanak sağlıyor. Konuyla ilgili olarak detaylı bilgi için Angular Resmi Dokümanına bakabilirsiniz.

Geliştirme esnasında Html sayfasında bazı değerleri göstermek için karmaşık hesaplamaların yapılması kaçınılmazdır. Bunun için Component tarafında metotlar hazırlayıp, Html sayfasından doğrudan fonskyonu çağırarak dönen değeri ekranda gösterilir. Zaman zaman bir çok geliştiricinin(Ben de dahil) önemsemediği bu durum, uygulama büyüdükçe performans konusunda sıkıntılar yaratabilir. Eğer bu fonksiyonun içerisinde servis çağrısı yada büyük logic var ise ciddi performans sorunları kaçınılmaz olacaktır. Örnekle açıklamak gerekirse(Saçma bir örnek idare edin :) ) :

En son eklenen dizi ve Dizilerin listelendiği bölüm Html sayfasında Metot gösterilmektedir. Uygulama açıldığında Metot çalışarak bilgiler ekranda göstermektedir. Buraya kadar her şey normal(getter ve metot uygulama açılırken 2 kez tetiklendi. Yani log’a 4 kayıt atıldı. Bu durum normal değil ama şimdilik görmezden gelelim). Kullanıcı text alana yeni bir bilgi eklemek istediğinde yazmış olduğu harf sayısının 2 katı kadar getter ve metot tekrardan çalışmaktadır. Ekle butonuna basınca getter ve metot 2 kere daha tetiklenmektedir. Demo: Stackblitz

Uygulamanın kodu:

Html sayfasında 14. satırda getdiziler() metodu kullanılarak ilgili bilgileri ekran da gösteriliyor.

Neden metot HTML’de birden fazla tetikleniyor?

Bu durum Angular’ın sunmuş olduğu Change Detection’den kaynaklamaktadır. Sayfa üzerinde, kullanıcının yapmış olduğu her bir işlemden sonra Angular sayfadaki değişiklikleri kontrol eder ve eğer değişiklik varsa DOM’da bu değişikliği gösterir. Detaylı bilgi için Emre Hızlı’nin Angular ChangeDetection Nedir? yazısına bakabilirsiniz.

Angular sayfadaki değişiklikleri kontrol ederken fonksiyonun değerinin değişip değişmediğini bilmez. Sayfanın güncel halini göstermek için, yapılan her bir kontrol esnasında getter ve metotlar tetiklenir. Örneğin Change Detection 100 kere çalışırsa getter ve metotlar da 100 kere çalışacaktır. Eğer sayfada çok fazla getter ve metot çağrıları yapılmış ise ciddi performans sorunları ortaya çıkacaktır.

Çözüm

1. Change Detection Stratejini (CDS) değiştirmek

Angular, Varsayılanı olarak Default olmak üzere 2 tane CDS sunmaktadır. Örnekteki sorunu çözmek için CDS’yi default’tan, onPush şeklinde değiştirebiliriz. onPush sadece ana component için çalışır, Child componentler için doğrudan çalışmaz. Child componentlere ait @Input’ların referanslar değişmesi, ana component veya child componente bulunan event’in tetiklenmesi, şablonlarda async pipe ile kullanılan observerlardan yeni bir değerin emit edilesi ve ChangeDetectorRef’in manuel tetiklensi durumunda Change Detection devreye girer.

@Input’larda

onPush stratejisini kullanılması durumunda son şekilde olacaktır: Bir önceki duruma göre, metot tetiklenmesi yarı yarıya düştü. Demo: StackBlitz

Uygulamanın Kodu :

Compenent’e ait kodda 7.satırdaki changeDetection: ChangeDetectionStrategy.OnPush ekleme yapıldı. Kodun diğer kısımlar bir önceki örnekle birebir aynı.

2. Pure Pipe Kullanmak:

Html kodunda metot yerine pure pipe kullanmak ciddi bir artışı sağlayacaktır. Angular’ın dokümanına göre, Pipe’in giriş değeri değişir ise CDS devreye girecektir. Pipe’lar hakkında bilgi için Sevilay Sarar’ın Angular Pipe Nedir? Custom Pipe Nasıl Yapılır? yazısına bakabilirsiniz

Pure Pipe ve onPush CDS kullanılması durumunda son durum şu şekilde olacaktır: Log’da “Pipe Tetiklendi” uyarısı uygulama açıldığında ve ekle butonuna basıldığında görüntülenmektedir. Bunun anlamı: Pipe’in değeri değişmedikçe CDS pipe için devreye girmiyor. Demo: StackBlitz

Uygulamanın Kodu :

Uygulamaya Pipe eklendi ve Html sayfasında 4. satırdaki değişiklikler yapıldı.

Kapanış

Şablonlarda Interpolation işlemlerinde metot kullanmak yerine pipe kullanılması ciddi performans kazanımı sağlayacaktır.

Ek bilgi:

Aşağıdaki kullanım şekilleri de işe yarayacaktır.

Getter / Setter Kullanmak

Getter’da da, metotta olduğu gibi aynı durum yaşanmaktadır. Ama Setter ile değişkenin değeri değiştiği ve getter sadece değişen değeri döneceği için performansta sıkıntı yaratmayabilir.

@Input’larda async pipe kullanmak

Observable’dan yeni bir değer emit ediliği zaman, async pipe compenente değişikliklerin için kontrol edilmesini söyler ve CDS devre girer.

İlginizi Çekebilir

Sizin bu durumlar için kullandığınız yöntemler varsa paylaşırsanız sevinirim

Bir sonraki yazıda görüşmek üzere.

--

--