چند روز پیش، من با افکتهای NgRx در یک برنامه کار میکردم، جایی که باید دادهها را از فروشگاه دریافت میکردم و آنها را با تماسهای سرویس شامل وظایف ناهمزمان ترکیب میکردم.
هنگام کار با جریان های ترکیبی، مهم است که اپراتور مناسب را انتخاب کنید. بستگی به عملیاتی دارد که می خواهیم انجام دهیم. شما می توانید یکی را انتخاب کنید concatMap، exhaustMap، mergeMap، و switchMap.
بنابراین، من تعطیلات هستم، بنابراین چند دقیقه وقت میگذارم تا چیزی بسازم که باید بین هر کدام انتخاب کنم و البته با استفاده از API و کار async با افکتها و تغییر حالت در کاهندهام.
ایده این مقاله این است که با NgRx در فرم خود بمانید و سعی کنید بدانید کدام و چه زمانی از آن عملگرها استفاده می شود، پس بیایید به شناسه بپردازیم!
این مقاله بخشی از مجموعه من در مورد یادگیری NgRx است. اگر می خواهید دنبال کنید، لطفا آن را بررسی کنید.
من می خواهم در برنامه خود بخشی ایجاد کنم تا مکان های مورد علاقه خود را در منورکا ذخیره کنم. من از mockAPI.io استفاده خواهم کرد، این یک سرویس عالی برای ساخت API جعلی و مدیریت عملیات CRUD است.
مخزن را شبیه سازی کنید start-with-ngrx. این پروژه شامل نمونه هایی از پست های قبلی من است.
https://github.com/danywalls/start-with-ngrx.git
به شعبه تغییر دهید crud-ngrx، که شامل تنظیمات زیر است:
NgRx با DevTools نصب و پیکربندی شد.
آماده پیکربندی با MockAPi.io APi
این PlacesService برای افزودن، بهروزرسانی، حذف و دریافت مکانها.
این PlaceComponentکامپوننت خالی برای بارگذاری روی places مسیر مسیر
هدف
هدف این است که با ساختن یک CRUD با NgRx و درک زمان استفاده از عملگرهای خاص RxJS، آنچه را که در مقالات قبلی آموختهایم تمرین کنیم. در این مقاله به موارد زیر خواهیم پرداخت:
یک حالت برای مکان ها ایجاد کنید.
اقداماتی را برای عملیات CRUD ایجاد کنید.
انتخابگرها را برای دریافت مکان ها ایجاد کنید.
از افکتها برای ایجاد، بهروزرسانی، حذف و دریافت کنشها استفاده کنید.
بهروزرسانی کنید و مکانها را از API حذف کنید.
بیا شروع کنیم!
اگر فقط به یادگیری در مورد اپراتورها علاقه دارید، به بخش پیاده سازی بروید.
ایجاد وضعیت مکان ها
ما میخواهیم وضعیت مکانها را مدیریت کنیم که باید موارد زیر را ذخیره کند:
فهرستی از مکانها از API.
مکان انتخاب شده برای ویرایش یا حذف.
یک پیام در حال بارگیری هنگام بارگیری داده یا انجام یک عمل.
در صورتی که هنگام افزودن، بهروزرسانی یا حذف خطایی وجود داشته باشد، پیام خطا.
با در نظر گرفتن این نکات، اجازه دهید یک فایل جدید ایجاد کنیم places/state/places.state.ts و اضافه کنید PlaceState تعریف را با یک نوع یا رابط (هر کدام که ترجیح می دهید) و وضعیت اولیه را برای مکان ها اعلام کنید.
کامل! ما حالت اولیه را برای مکان ها داریم. زمان ایجاد اقدامات است!
Actions را ایجاد کنید
مشابه پست قبلی خود، از آن استفاده خواهیم کرد createActionGroup ویژگی برای گروه بندی اقدامات ما مربوط به PlaceState. ما دو نوع اقدام داریم: اقداماتی که توسط کاربر در UI راه اندازی می شود و اقدامات مربوط به فرآیند API. بنابراین، من ترجیح می دهم اقدامات را به دو نوع تقسیم کنم: PlacePageActions و PlaceApiActions.
ابتدا اقدامات را از روی تعریف می کنیم PlacePage برای انجام موارد زیر:
درخواست بارگذاری مکان ها: load Places
افزودن/بهروزرسانی مکان: مکانی را با شیء Place اضافه کنید
ما اقداماتی برای انجام از اثرات داریم. این کنشها با API مرتبط هستند و هنگام بارگیری، افزودن، بهروزرسانی یا حذف با موفقیت یا شکست، به درخواست و پاسخ رسیدگی میکنند.
ما اقدامات خود را داریم، پس وقت آن است که کاهش دهنده را ایجاد کنیم تا وضعیت خود را به روز کنیم!
کاهنده
کاهنده مسئول به روز رسانی وضعیت ما بر اساس اقدامات است. در برخی موارد، میخواهیم وضعیت خود را هنگام راهاندازی یک عمل یا بر اساس نتیجه یک عمل در افکت بهروزرسانی کنیم.
مثلا اولین اقدام loadPlaces توسط PlaceComponent. در آن لحظه، من می خواهم صفحه بارگیری را نشان دهم، بنابراین تنظیم کردم loading به true. در موارد دیگر، مانند loadSuccess عمل، آن را از اثر زمانی که ما آمده است PlaceService داده ها را برمی گرداند.
هر اکشنی را برای ایجاد تغییرات در وضعیت مورد نیاز خود اجرا کنید، من قصد ندارم هر کدام را توضیح دهم اما کد نهایی به نظر می رسد:
ما کاهنده خود را آماده واکنش به اقدامات هستیم. حالا قسمت هیجان انگیز می آید: جلوه ها! بیایید آن را انجام دهیم!
تاثیر
افکت به کنشها گوش میدهد، وظایف همگام را انجام میدهد و سایر اقدامات را ارسال میکند. مهم است که بدانید از کدام اپراتور RxJS استفاده کنید—concatMap، exhaustMap، mergeMap، یا switchMap– برای جلوگیری از ایجاد شرایط مسابقه در کد خود.
شرایط مسابقه چیست؟
شرایط مسابقه زمانی اتفاق میافتد که چندین کار ناهمزمان (مشاهدهپذیر) به طور همزمان اجرا میشوند و به روشهایی که ما نمیخواهیم با یکدیگر تداخل میکنند. این می تواند باعث رفتار غیرمنتظره یا اشکالات شود زیرا زمان بندی این وظایف به خوبی کنترل نمی شود.
exhaustMap: اگر درخواستی در حال انجام است، درخواست های جدید را نادیده می گیرد.
concatMap: هر درخواست را یکی پس از دیگری به ترتیب پردازش می کند.
mergeMap: به همه درخواستها اجازه میدهد تا همزمان اجرا شوند، اما برای جلوگیری از مشکلات باید پاسخها را به درستی مدیریت کنید.
switchMap: در صورت ورود درخواست جدید، درخواست قبلی را لغو می کند. این تضمین می کند که فقط آخرین درخواست پردازش می شود.
بیایید از هر یک در اثر خود استفاده کنیم!
اگر میخواهید درباره این اپراتورها بیشتر بدانید، به شدت توصیه میکنم ویدیوهای @decodedfrontend را بررسی کنید
ExhaustMap
exhaustMap درخواستهای جدید را نادیده میگیرد، اگر درخواستی از قبل در حال انجام باشد، برای سناریوهایی مفید است که فقط اولین درخواست باید پردازش شود، و درخواستهای بعدی باید تا زمانی که اولین درخواست تکمیل شود نادیده گرفته شوند. به عنوان مثال لیست مکان ها را دریافت کنید.
concatMap به ما کمک میکند تا کنشها را ترسیم کنیم و قابل مشاهدههایمان را به ترتیب در یک مشاهدهپذیر ادغام کنیم، اما قبل از ادامه دادن به مورد بعدی منتظر میماند تا هر یک کامل شود. زمانی که میخواهیم مطمئن شویم همه چیز به ترتیب اعلامشده پیش میرود، ایمنترین اپراتور است. برای مثال، اگر مکانی را بهروزرسانی میکنیم، میخواهیم اولین بهروزرسانی قبل از راهاندازی مکان دیگری تکمیل شود.
این mergeMap اپراتور بدون حفظ نظم سریع اجرا می شود. این اجازه می دهد تا همه درخواست ها به طور همزمان اجرا شوند، اما برای جلوگیری از شرایط مسابقه باید پاسخ ها را به درستی مدیریت کنیم. این برای افزودن و حذف اقدامات عالی است.
اما وقتی کاربر مورد را حذف میکند، باید دوباره دادهها را دریافت کنم، بنابراین باید به اکشن deleteSuccess گوش دهم تا دوباره دادهها را دریافت کنم و وضعیت را تازه کنم.
switchMap زمانی استفاده کنید که میخواهید مطمئن شوید که فقط آخرین درخواست پردازش میشود و درخواستهای قبلی لغو میشوند. ایده آل برای سناریوهایی مانند تکمیل خودکار یا جستجوی زنده. این کمک می کند تا مشاهده پذیرهای فعال را با یک مورد جدید لغو کنید. در سناریوی من موردی ندارم، اما ذکر آن برای مراقبت مهم است.
ثبت اثرات و کاهش دهنده
زمان ثبت ایالت جدیدم فرا رسیده است placesReducer و placesEffectsرا باز کنید app.config.ts،
افزودن کلید جدید در provideStore، places: placesReducer
وارد کردن تمام جلوه ها از places.effects.ts ، اضافه کردن به provideEffects تابع.
Mm… خوب، ما اثر داریم اما چگونه داده ها را در کامپوننت دریافت می کنیم؟ من باید یک انتخاب کننده ایجاد کنم تا حالت را به دست بیاورم، بیایید آن را انجام دهیم!
انتخابگرها
فایل را ایجاد کنید places.selector.ts، با استفاده از createFeatureSelector تابع، از نوع PlaceState استفاده کرده و یک نام تعریف کنید.
بعد، با استفاده از selectPlaceState، استفاده کنید createSelector تابعی برای ایجاد انتخابگر برای بخشی در وضعیت ما، مانند places، loading، error و activePlace و صادرات آن انتخابگر مصرف در کامپوننت.
مراحل نهایی استفاده از انتخابگرها و ارسال اکشن ها از کامپوننت ها، باز است places.component.ts ، به فروشگاه تزریق کنید. بعد اعلام کنید place$، error$ و placeSelected$ برای ذخیره مقدار از انتخابگرها.
در قالب، در selectedPlace مشترک شوید و برای آسان کردن آن و کوتاه نگه داشتن مقاله، یک پیوند ورودی به selectedPlace.name اضافه کنید، با استفاده از متغیرهای الگو، یک مرجع به نام ورودی #placeName ایجاد کنید.
در دکمه Save کلیک می کنیم، محل انتخاب شده و نام جدید را پاس می کنیم.
من می توانم کمی بهتر باشم، اما مقاله کمی طولانی تر شده است، اگر راه بهتری می دانید با راه حل خود نظر دهید یا یک روابط عمومی ارسال کنید و مطمئناً کد شما را اضافه می کنم و روی آن ذکر می کنم!.
}
@if (placeSelected$ | async; as selectedPlace) {
class="modal is-active">
class="modal-background">
}
نتیجه
در این پروژه، نحوه ایجاد یک برنامه CRUD با استفاده از NgRx و عملگرهای مختلف RxJS برای مدیریت اقدامات ناهمزمان را بررسی کردیم. ما همچنین مدیریت درخواست ها و پاسخ های HTTP از یک API را تمرین کردیم. با این حال، من احساس می کنم جایی برای پیشرفت وجود دارد.
نکاتی برای بهبود:
برای پرداختن به این مشکلات، من قصد دارم پروژه را با ترکیب موجودیتهای NgRx با روتر NgRx برای سادهسازی کد و بهبود قابلیت نگهداری، بازسازی کنم.