Angular 16 – Signals Yapılanmasını Detaylı İnceleyelim
Bu içeriğimizde Angular 16 ile hayatımıza giren, geliştiriciler açısından oldukça iş kolaylaştırıcı ve bir o kadar da uygulama açısından da performans arttırıp maliyet kırıcı bir özellik olan, teknik olarak bir değişkenin verisel açıdan değişikliğe uğradığı anı yakalayabilmemiz için yeni bir yol sunan ve böylece kodu daha reaktif bir gale getirmemizi sağlayan Signal’ları tam teferruatlı inceliyor olacağız. O halde buyurun başlayalım.
Signals Nedir?
Signals; bir değişkenin, değerinin değişmesini takip eden ve değişiklik meydana geldiği taktirde reaktif bir tutum sergileyerek bunu haberdar eden yeni bir özelliktir. Bunu daha iyi anlayabilmek için aşağıdaki örnek üzerinden ilerleyelim;
let x = 5;
let y = 15;
let z = x + y;
console.log(z); // 20
x = 10;
console.log(z); // 20
|
Yandaki çalışmaya göz atarsanız eğer z değişkeni x ile y değişkenlerinin toplamından oluşmakta ve 4. satırda bu toplam sonucu console’a yazdırılmaktadır. Buraya kadar her şey normalken, sizce 5. satırda x değişkenin değerinin değiştirilmesi 6. satırdaki z değişkeninin değerinde fark yaratacak mıdır? Tabi ki de hayır, değil mi? Çünkü z değişkeninin değeri, 3. satırdan itibaren x ve y’den bağımsız olarak varlık gösterecek ve süreçte x’de yahut y’de olabilecek herhangi bir değişiklik z’yi etkilemeyecektir! |
Halbuki sizler, yazılan kodun x veya y üzerinde olacak değişikliklere karşı tepki vermesini istiyorsanız ya da bir başka değişle x veya y değerleri değiştiği taktirde z toplam sonucunun yeniden hesaplanmasını istiyorsanız, reaktif bir tutum sergilemeniz gerekmektedir. Bunun için de aşağıdaki gibi bir getter property’den istifade edebilirsiniz.
get total() {
return this.x + this.y;
}
|
Evet, bu şekilde reaktif davranış söz konusu olmuş olabilir amma velakin bu örneği property ile değil de, direkt olarak değişken üzerinde bir değişiklik olduğu taktirde uygulamak isteseydik işte o taktirde Signal’lardan aşağıdaki gibi istifade edebiliriz. |
let x = signal(5);
let y = 15;
let z = computed(() => x() + y);
console.log(z()); // 20
x.set(10)
console.log(z()); // 25
|
Görüldüğü üzere; signal fonksiyonu ile değer değişikliği takip edilecek olan x değişkeni tanımlanmakta, computed fonksiyonu ile ise bu değişkenin değeri değiştiği taktirde z’nin değeri yeniden hesaplanmaktadır. Değer değişiminde ise 5. satırda olduğu gibi set fonksiyonu kullanılmaktadır. Tabi ki de burada bahsi geçen fonksiyonları ve bu fonksiyonların varlık sebeplerini içeriğimizin devamındaki satırlarda başlık başlık inceliyor olacağız. Şimdilik reaktif bir tutumun Signals özelliğiyle gelen basit fonksiyonlarla nasıl kolayca sağlanabildiğini görmeniz açısından bu şekilde basit bir örneklendirmeyle hızlı girizgâh eylemiş bulunuyoruz. |
Bu noktada anlayacağınız; Signal’lar, Angular çalışmalarında değişkenlerin değerlerini (değişken seviyesinde) dinamik olarak takip etmemizi ve olası değişiklik durumlarında türlü nitelikleriyle aksiyonlar almamızı ve bu aksiyonlar eşliğinde hedeflediğimiz çalışmalarımızı kolaylıkla yapmamızı sağlayan özelliktir.
Signals, değişkenlerdeki verisel değişikliklere(change detection) karşın oldukça iyi kontrol sağlamakta, uygulamanın performansını arttırmakta ve change detection açısından etkili bir kullanıcı deneyimi sunmaktadır.
Signal’lar Zone.JS’e ihtiyaç duymaksızın çalışırlar!
Evet, Signal’lar Angular’da ki Zone.JS’e ihtiyaç duymaksızın çalışma sergileyen yapılanmalardır. Zone.JS, Angular’ın asenkron işlemleri yönetirken, etkin bir şekilde çalışmasını ve event’leri işlemesini sağlayan bir çalışma modelidir. Bu model, Angular uygulamasındaki component’lerin ve diğer parçaların etkileşimini düzenlemekte ve performansı optimize edebilmektedir. Yani anlayacağınız Zone.JS; Angular uygulamasındaki herhangi bir değişikliği takip eden ve değişiklik yapılan DOM elemanlarının hemen hemen herhangi bir yerinde/noktasında çalışan component’lerin bu değişikliğe tepki vermesini sağlayan bir kütüphanedir.
Signal’ler Nasıl Tanımlanır ve Kullanılır?
Bir signal’ı tanımlayabilmek için @angular/core path’inde bulunan signal fonksiyonundan istifade ediyoruz.
import { signal } from '@angular/core';
.
.
.
let x = signal(5);
Görüldüğü üzere yukarıda ‘5’ değerine sahip bir signal tanımlanmıştır. Bu signal’ın türüne göz attığımızda aşağıdaki gibi ‘WritableSignal’ olduğunu göreceğiz;
Yani hem yazılabilir hem de okunabilir bir signal tanımlamış oluyoruz. Bunu daha da netleştirebilmek için ilgili değişkenin türünü aşağıdaki gibi de belirtebiliriz.
let x: WritableSignal<number> = signal(5);
Tabi bu tanımlama sürecinde isterseniz oluşturulacak signal’ın türünü de generic olarak belirtebilirsiniz.
let x: WritableSignal<string> = signal<string>("merhaba");
Tanımlanmış bir signal’ı kullanmak ya da bir başka deyişle signal’ın değerini okumak istiyorsanız eğer ihtiyaç noktasında x() gibi fonksiyonvari bir şekilde çağırmanız yeterlidir. Burada parantezlerin özellikle boş olmasına özen göstermeniz gerektiğine dikkatinizi çekerim.
Signal Fonksiyonları
Şimdi signal’ler üzerinde işlevsel davranışlar sergilemizi sağlayan önemli fonksiyonları inceleyelim.
- set Fonksiyonu
Bir signal’e ilk değerinin dışında farklı değer atamamızı yahut var olan değeri değiştirmemizi sağlayan fonksiyondur.let x: WritableSignal<number> = signal<number>(3); console.log(x()); x.set(5); console.log(x());setfonksiyonunun detayında bilinmesi gereken kritik şudur ki; bir signal’da aşağıdaki gibisetfonksiyonuyla art arda değer ataması gerçekleştirilirse, template güncellemesi süreçteki tümsetişlemleri için değil, sadece sonuncusu için gerçekleştirilecektir.@Component({ selector: 'app-root', standalone: true, template: ` <button (click)="onSet()">set</button> <br> {{x()}} ` }) export class AppComponent { x: WritableSignal<number> = signal<number>(3); onSet() { this.x.set(5); this.x.set(10); this.x.set(15); this.x.set(20); this.x.set(25); } }Haliyle yukarıdaki örneği incelersek eğer butona tıklanıldığı taktirde x signal’ının değeri önce 5, sonra sırasıyla 10, 15, 20 ve son olarakta 25 olarak değiştirilecektir. Amma velakin template ki 6. satıra ise bu değişiklik tüm kademeler için yansıtılmayacak, sadece 25 değerinin atandığı sonuncu
setişlemi için yansıtılacaktır. - update Fonksiyonu
Signal’ın değerini, mevcut olan değerle birlikte güncellememizi sağlayan fonksiyondur.let x: WritableSignal<number> = signal<number>(3); console.log(x()); //3 x.update(data => data * 5); console.log(x()); //15 - mutate Fonksiyonu
Signal, yapısal olarak içerisinde object türünden değer/nesne barındırabilecek bir özelliktir. Dolayısıyla aşağıdaki gibi signal’da ki değer bir objeyse, ilgili nesnenin içerisindeki alanlara karşınmutatefonksiyonu ile gerekli değişiklikler uygulanabilmekte ve böylece signal içerisindeki nesnenin değerleri mutasyona uğratılabilmektedir.let person: WritableSignal<Person> = signal<Person>({ name: 'Hilmi', surname: 'Celayir', age: 45 }); console.log(person()); person.mutate(obj => obj.name = "Şuayip"); console.log(person()); - computed Fonksiyonu – computed Signal
Computed fonksiyonu, değerini içerisine verilen signal(ler)in değer değişiminden alan ve sonuç olarak geriye ‘Signal’ türünden bir değer dönen fonksiyondur.@Component({ selector: 'app-root', standalone: true, template: ` <button (click)="onComputed()">computed</button> <br> {{x()}} ` }) export class AppComponent { x: WritableSignal<number> = signal<number>(1); y: Signal<string> = computed(() => `x değişkeninin değeri ${this.x()} olarak değişti.`); onComputed() { this.x.update(data => data + 1); console.log(this.y()); } }Yukarıdaki kod bloğunu incelerseniz eğer biri signal(x) biri de computed(y) olmak üzere iki değişken mevcuttur. Butona her tıklandığı vakit x signal’inin değeri
updateedilmekte ve console’a ‘y’ computed signal’inin değeri yazılmaktadır.
Şimdi computedfonksiyonundaki maksada gelirsek eğer, içerisinde kullanılan signal(lar)’dan en az birinde olacak her değer değişimine karşı tepki vermekte ve yeniden tetiklenmektedir. Böylececomputedsayesinde, birden fazla signal’ın değer değişimi takip edilebilmekte ve bu değişimlere karşın sentez yeni değerler üretilebilmektedir. Ayrıcacomputedfonksiyonu değer üreteceği için read-only bir davranış sergileyecektir ve bu da ‘Signal’ türüyle ifade edilmektedir.Computed fonksiyonu içerisinde kullanılan signal’ler dependencies/bağımlılıklar olarak nitelendirilmektedirler.
Ayrıca
computedfonksiyonunun dependency’leri dinamik bir davranış sergilemektedir. Bunun ne demek olduğunu anlayabilmek içincomputed‘ın çalışmasını biraz daha derinlerde gözlemlemek gerekmektedir. Bunun için aşağıdaki kod bloğunu inceleyiniz.@Component({ selector: 'app-root', standalone: true, template: ` <button (click)="onComputed()">computed</button> <br> {{x()}} ` }) export class AppComponent { check: WritableSignal<boolean> = signal<boolean>(false); x: WritableSignal<number> = signal<number>(1); y: Signal<string> = computed(() => { if (this.check()) return `x değişkeninin değeri ${this.x()} olarak değişti.`; return ""; }); onComputed() { this.x.update(data => data + 1); console.log(this.y()); } }Yukarıdaki çalışmada dikkat ederseniz
computedfonksiyonu içerisinde ‘check’ signal’i üzerinden bir kontrol gerçekleştirilmektedir. Bu kontrol true olduğu sürece x signal’inin değericomputedfonksiyonunun bağımlılığı olarak değerlendirilecektir. Yok eğer false olursa x signal’i bucomputedfonksiyonu tarafından bir bağımlılık olarak değerlendirilmeyecektir. - effect Fonksiyonu – effect Side
effectfonksiyonu yalnızca constructor seviyesinde kullanılabilmektedir.Bir signal’ın değeri değiştiğinde bazı kodları çalıştırmak isteyebiliriz. Bunun için
effectfonksiyonunu kullanabiliriz.@Component({ selector: 'app-root', standalone: true, template: ` <button (click)="onSet()">set</button> <br> {{x()}} ` }) export class AppComponent { constructor() { effect(() => console.log(`x değişkeninin mevcut değeri : ${this.x()}`)) } x: WritableSignal<number> = signal<number>(1); onSet() { this.x.update(data => data + 1); } }Görüldüğü üzere 11. satırda tanımlanmış olan
effectfonksiyonu ile x signal’ında olabilecek verisel değişikliklere karşın ekstradan işlemler yürütebilmekteyiz.Effect fonksiyonu her daim değişiklik algılama sürecini(change detection) asenkron bir şekilde yürütür.
Uygulama süreçlerinde
effectfonksiyonunun işlevine pek ihtiyaç duyulacak olmasa da, nadiren de olsa aşağıdaki gibi kritik durumlarda biçilmiş kaftan görevi görebilir;- Verileri değişiklik durumlarında loglarken
- Veriler, değişiklik neticelerinde local storage gibi ortamlara senkronize edilirken
- Özel DOM davranışları eklenirken
Ayrıca bir effect oluşturulduğunda, onun yaratıldığı component, directive yahut pipe destroy edildiğinde otomatik effect’te yok edilir. Bunun dışında manuel bir şekilde oluşturulmuş bir effect’i destroy etmek istiyorsanız aşağıdaki gibieffectfonksiyonunun döndürdüğü ‘EffectRef’ türünden olan nesneyi bir referansla karşılayarak, ‘destroy’ fonksiyonunu iradenizle çağırabilirsiniz.const _effect: EffectRef = effect(() => console.log(`x değişkeninin mevcut değeri : ${this.x()}`)) _effect.destroy();Peki hoca, bir effect içerisinde herhangi bir signal’ın değerini değiştirebilir miyiz? Ki değiştirdiğimizi düşündüğümüzde sonsuz bir döngü ihtimali var gibi…
Güzel soru… Evet,
effectgibi bir fonksiyonu gördüğünde insanın aklına direkt bu tarz bir soru geliyor diyebiliriz. Şimdi bu soru nezdindeeffectiçerisinde bir signal’in değerini değiştirmeye çalışarak gözlemde bulunalım.effect(() => { console.log(`x değişkeninin mevcut değeri : ${this.x()}`); this.x.update(data => data + 1); })Bu işlem neticesinde aşağıdaki gibi bir hatayla karşılaşıyoruz:
Hatanın metinsel hali;ERROR Error: NG0600: Writing to signals is not allowed in a `computed` or an `effect` by default. Use `allowSignalWrites` in the `CreateEffectOptions` to enable this inside effects.Yani anlayacağınız
effectve hattacomputediçerisinde herhangi bir signal’in değerini değiştiremiyoruz. Ama bu davranışı gerçekleştirebilmek içinallowSignalWritesözelliği ile müdahalede bulunabiliyoruz.effect(() => { console.log(`x değişkeninin mevcut değeri : ${this.x()}`); this.x.update(data => data + 1); }, { allowSignalWrites: true })allowSignalWrites özelliği ile effect içerisinde signal değerinin değiştirilmesine izin verilmesi pekte tavsiye edilen bir yaklaşım değildir!
effectile ilgili inceleyeceğimiz bir başka konu ise cleanup function‘dır. Nedir bu cleanup function diye sorarsanız eğer şöyle izah edelim… Effect’ler, ister istemez bazı durumlarda uzun süren operasyonları başlatabilir ve bu operasyonları üst üste bindirebilirler. Şöyle ki;effect(() => { console.log(this.x()); const timer = setTimeout(() => { console.log("Processing..."); }, 2000); })
Yukarıdaki kod bloğunu incelerseniz x signal’ında olacak her verisel değişiklikte bu effecttetiklenecek ve her tetiklenmeye karşılık 2 saniyelik bir process başlatacaktır. Ve bu process’ler arkaplanda effect’ler için işlemeye devam edecektir. Bunun için yandaki görseli inceleyebilirsiniz. Effect’in içerisindeki process’ler işlemleri bittikçe nihayete ermekte ve console’a çıktı vermektedirler.Bizler bu tarz
effect‘in seri bir şekilde tetiklendiği durumlarda,effectiçerisindeki process bitmeden başka bir tetiklenme neticesinde başlayan process’i işlemektense, yeni bir process başladığı taktirde bir öncekieffect‘in process’ini durdurmak ve böylece en sonuncueffect‘e göre işlem yapmak istiyorsak cleanup function‘ı kullanabiliriz.cleanup function‘ı, bir sonraki
effectbaşlamadan önce yahut ilgilieffectdestroy edildiğinde çağrılan bir callback function‘dır ve aşağıdaki gibi kullanılır.effect(onCleanup => { console.log(this.x()); const timer = setTimeout(() => { console.log("Processing..."); }, 2000); onCleanup(() => { clearTimeout(timer); }) })
Görüldüğü üzere; her effectiçerisindeki process, işlemi bitmeksizin bir sonrakieffecttarafından yeniden başlatılma ihtimaline nazaran 8 ile 10. satır aralığında ‘onCleanup’ fonksiyonu tarafından iptal edilmekte ve process süreci bir sonrakieffect‘e bırakılmaktadır. Haliyle bu şekilde çalışmanın neticesinde yandaki görseldeki davranışla karşılaşılmaktadır.Anlayacağınız, callback function bizlere, yeni bir
effectfire olduğu taktirde eskieffect‘leri destroy eden bir ortam sağlamakta ve böylece olası maliyetleri mümkün mertebe düşürebileceğimiz senaryolarda daha performanslı bir yaklaşım sergilememize imkan tanımaktadır.
Cleanup function, yeni effect fire olduğunda eski effect’leri destroy eder!
Ve son olarak bir signal’ın değeri değiştiğinde herhangi bir
effect‘in tetiklenmesini istemiyorsak nasıl bir davranış sergilememiz gerektiğini inceleyelim. Bunun içinuntrackedfonksiyonunu kullanabiliriz.untrackedfonksiyonunda,effecttarafından bağımlılık olarak değerlendirilmemesi gereken bazı harici kodlar çalıştırılabilir.import { Component, WritableSignal, effect, signal, untracked } from '@angular/core'; @Component({ selector: 'app-root', standalone: true, template: ` <button (click)="onSet()">set</button> <br> {{x()}} ` }) export class AppComponent { constructor() { effect(() => { console.log(`x değişkeninin mevcut değeri : ${this.x()}`); untracked(() => { this.y.update(data => data - 1); console.log(`y değişkeninin mevcut değeri : ${this.y()}`); }); }) } x: WritableSignal<number> = signal<number>(1); y: WritableSignal<number> = signal<number>(999); onSet() { this.x.update(data => data + 1); } }Yukarıdaki kod bloğunu incelerseniz eğer x signal’ının değerine göre tepki verecek bir
effectolduğunu göreceksiniz. Bueffectiçerisindekiuntrackedfonksiyonu ile yürütülen işlemlereffect‘in bağımlılık göstermeyeceği çalışmaları ifade etmektedir. Haliyle y signal’ının değerinin değişmesi ve console’a yazdırılması ancak x signal’ının değeri değiştiğindeeffect‘in tetiklenmesiyle gerçekleşecektir.
Böylece signal’ler üzerinde işlevsel davranışlar sergilememizi sağlayan fonksiyonları tam teferruatlı incelemiş olduk. Şimdi ise observable ve signal arasındaki dönüşümleri incelemeye odaklanabiliriz.
RxJS Interop
Angular 16. versiyonunda observable’lar ile signal’lar arasında dönüşüm gerçekleştirebilmek için @angular/core/rxjs-interop path’inde toSignal ve toObservable fonksiyonları gelmiş bulunmaktadır. Şimdi bu fonksiyonlara tek tek odaklanarak kullanım durumlarının farkındalığını oluşturalım.
toSignal ve toObservable fonksiyonlarının her ikisi de constructor seviyesinde kullanılmalıdır! Aksi taktirde uygulamanın hata vermesine sebebiyet verirler.
- toSignal Fonksiyonu
toSignalfonksiyonu ile bir observable nesnesi read-only olan(yani Signal referansına sahip) bir signal’a dönüştürülmektedir. Misal olarak aşağıdaki kod bloğunu incelersek eğer;import { Component, effect } from '@angular/core'; import { interval } from 'rxjs'; import { toSignal } from '@angular/core/rxjs-interop'; @Component({ selector: 'app-root', standalone: true, template: `` }) export class AppComponent { constructor() { effect(() => console.log(`counter signal'ının değeri : ${this.counter()}`)) } counter$ = interval(1000); counter = toSignal(this.counter$); }
Örnekte görüldüğü üzere intervalile 1 saniyelik bir periyoda sahip olan observable yaratılmakta ve butoSignalfonksiyonu ile signal’a dönüştürülmektedir. Haliyle ‘counter’ signal’ının değeri her 1 saniyede bir değişeceği için her değişime karşılık 12. satırda tanımlanmış olaneffectfonksiyonu tepki verecek ve ilgili signal’ın değerini yandaki görselde olduğu gibi console’a yazdıracaktır.Burada unutulmaması gereken husus şudur ki;
toSignalfonksiyonu, observable’a hemen subscribe olacaktır ve bu durum bazı durumlarda istenmeyen yan etkilere(side effect) sebep olabilir.Ayrıca observable’ların bir başlangıç değeri olmayacağı için
toSignalfonksiyonu ‘Signal<number | undefined>’ gibi bir referans üretebilmektedir, bundan dolayı ilgili fonksiyonun kullanımı neticesinde üretilecek signal’a ilk değerini vermek istiyorsanız aşağıdaki gibi ‘initialValue’ property’sini kullanabilir ve böylece üretilecek signal’da ki undifined terimini kaldırıp, kesin bir referansla üretilmesini sağlayabilirsiniz.@Component({ selector: 'app-root', standalone: true, template: `` }) export class AppComponent { constructor() { effect(() => console.log(`counter signal'ının değeri : ${this.counter()}`)) } counter$ = interval(1000); counter = toSignal(this.counter$, { initialValue: 999 }); }Yukarıdaki tanım neticesinde ‘counter’ signal’ı ilk olarak 999 değerine sahip olacak sonrasında ise ‘counter$’ observable’ında ki akışa göre değeri güncellenecektir.
Tabi ayriyeten bu işlemi observable’ın kaynağı hemen yayması durumunda ‘requireSync’ property’sine true değerini vererekte gerçekleştirebiliriz.@Component({ selector: 'app-root', standalone: true, template: `` }) export class AppComponent { constructor() { effect(() => console.log(`counter signal'ının değeri : ${this.counter()}`)) } counter$ = interval(1000); counter = toSignal(this.counter$, { requireSync: true }); }Yukarıdaki koda göz atmadan önce, bir önceki satırda ‘…kaynağı hemen yayması durumunda…’ ibaresine odaklanmanızı istiyorum. Buradan anlaşılan, signal’a dönüştürülmüş observable eğer ki hemen veri yayınlamazsa bu yöntem Angular tarafından hata fırlatılmasına sebebiyet verecektir.
Haliyle bu soruna karşın çözüm getirebilmek için ilgili observable’a aşağıdaki gibi bir başlangıç değeri vermemiz yeterli olacaktır.import { Component, effect } from '@angular/core'; import { interval, startWith } from 'rxjs'; import { toSignal } from '@angular/core/rxjs-interop'; @Component({ selector: 'app-root', standalone: true, template: `` }) export class AppComponent { constructor() { effect(() => console.log(`counter signal'ının değeri : ${this.counter()}`)) } counter$ = interval(1000).pipe(startWith(0)); counter = toSignal(this.counter$, { requireSync: true }); }Ayrıca son olarak
toSignalfonksiyonu ile dönüştürülen observable bir hata verdiğinde bunu aşağıdaki gibi try – catch blokları eşliğinde kolayca handle edebilir ve uygulamanızdaki çalışmalara devam edebilirsiniz.export class AppComponent { constructor() { effect(() => console.log(`counter signal'ının değeri : ${this.counter()}`)) } counter$ = interval(1000).pipe(startWith(0)); counter = toSignal(this.counter$, { requireSync: true }); ngOnInit() { try { this.counter(); } catch (e) { console.log(e); } } } - toObservable Fonksiyonu
Bir signal’ı, observable nesnesine dönüştüren fonksiyondur. Bunun için aşağıdaki kod bloğunu inceleyebilirsiniz.import { Component, WritableSignal, effect, signal } from '@angular/core'; import { toObservable } from '@angular/core/rxjs-interop'; @Component({ selector: 'app-root', standalone: true, template: `` }) export class AppComponent { count: WritableSignal<number> = signal(1); count$ = toObservable(this.count); increment() { setTimeout(() => { this.count.update(data => data + 1); this.increment(); }, 1500); } ngOnInit() { this.increment() this.count$.subscribe(data => console.log(data)); } }
NgRx 🤝 Signals
İçeriğimiz boyunca bu satırlara kadar signal’ler için incelediğimiz tüm niteliklerin esasında state management açısından da bizlere oldukça kolaylık ve bir o kadar da performanslı bir yaklaşım sergileme imkanı getirdiğinin farkındasınızdır. Bu durum, signal’lerin gelecekteki Angular projelerinin çoğunda NgRx’in yerini alma potansiyeline sahip olduğunu göstermektedir. Bu şimdilik bir öngörüdür. Tabi ki de zamanın getirdikleriyle bu öngörüyü olgunlaştıracak yeni durumları bir bütün olarak masaya yatıracak ve hep beraber konuya dair hususi başlık altında, başka bir içeriğimizde incelemede bulunuyor olacağız.
Nihai olarak;
Signal’lar, Angular uygulamalarını daha hafif kılmaya ve zamanla mimariyi Zone.JS gibi bir kütüphanenin etkisinden törpülemeye işaret etmektedirler. Evet, signal’ler henüz erken bir aşamadadır lakin bu durum Angular’ın gidişatı açısından parlak bir geleceğe heyecan yaşamamızı engelleyici bir unsur değildir.
İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…


Hocam cok aciklayici ve faydali bir makale olmus .Elinize saglik.Angular 16 da ki yenilikler hakkinda daha cok makale bekliyoruz sizden.
tesekkurler
Sevgili okurların dikkatine;
Angular 17’de mutate fonksiyonu çıkarılmıştır. Onun yerine update fonksiyonu kullanılmalıdır!
Örnek olarak;
person: WritableSignal<Person> = signal({ name: "Gençay", surname: "Yıldız" }); ngOnInit() { this.person.update(p => { p.name = "123" return p; }) }Bilginize…