Dibo

معلومة سريعة في 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' })
)