
معلومة سريعة في Angular
لو عندك component وانت عاوز تـ subscribe لـ observable معين عشان مثلا تجيب داتا من السيرفر فانت غالبا هتعمل حاجة زي كدة
class MyComponent{
data: Data;
constructor(private service: MyService){}
ngOnInit(){
this.service.getData().subscribe({
next: res=>{ this.data = data; }
})
}
}
ادي بصة كدة ع الكود دة, لو ماحستش ان فيه حاجة غلط في الكود يبأة انت عندك مشكلة في كل مشاريع انجولار اللي انت شغال عليها
هو في مشكلتين هنا:
1- مشكلة typing, لان الفترة اللي بين الـ subscription وأول emit للداتا, data هنا هتكون undefined وليس Data
فالمفروض هنا نعدل الكود عشان يبأة كدة
data?: Data // equivalent to `data: Data | undefined`
2- مشكلة memory leak لانك ماعملتش unsubscribe للـ observable بعد ما خلصت شغلك
وهنا تقدر تعمل ال unsubscription دة اما بعد ما اول value تجيلك علي طول لانك غالبا مش محتاج اي values تاني بعد كدة
يا اما في ngOnDestroy hook
بس مش دة اللي انا جاي اكلمك فيه ..
الكود اللي فوق دة نقدر نبسطه أكتر من كدة ونستغني تماما عن ngOnInit و ngOnDestroy وكمان هيحل المشكلتين اللي فوق دول اوتوماتيك
ودة اعادة كنابة الكود بعد التظبيط
class MyComponent{
readonly data$ = this.service.getData()
constructor(private service: MyService){}
}
لاحظ هنا ان انا ماحتجتش اصلا احط الـ type بتاع data لانه هييجي من تعريف getData() مباشرة
ولاحظ كمان اني خليته readonly لاني مش ناوي اغير قيمته تاني ودة هيوفر اكتر في الميموري, بعكس فوق اضطريت اغير قيمته من undefined للقيمة الحقيقية بعد ما الداتا الحقيقية بتوصل
لاحظ برضو ان انا غيرت اسمه من data لـ data$ لانه اصبح observable
دلوقت بأة في التمبليت ممكن نستخدم الـ observable مباشرة بدل الـ data object عن طريق asyncPipe
<p> {{ (data$ | async).someValue }} </p>
طبعا هنا هيواجهنا شوية مشاكل, بس انا جايبلك الحل
اول مشكلة اننا ساعات بتحتاج نغير الداتا لما توصل وقبل ما نبعتها التمبليت زي كدة
this.service.getData().subscribe({
next: res=>{
let newData = {...res, 'key: value'}
this.data = newData;
}
})
هنا احنا اضطرينا نعمل subscription عشان احنا مضطرين نتعامل مع الداتا قبل ما توصل التمبليت, فاحتاجنا تاااااااني نرجع ngOnInit ونخلي بالنا من مشكلة ال typing اللي غالبا بنعملها غلط ومشكلة الميموري ليك اللي بتحصل بسبب اننادايما ننسي نعمل unsubscriton
حل المشكلة دي بسيط جدا اننا نعمل pipe لل observable عشان نعرفه الـ mutations اللي احنا حابين نطبقها علي الداتا أول ما توصل
فممكن ببساطة نعمل كدة:
readonly data$ = this.service.getData().pipe(
map(res=> {...res, key: 'value' })
)