در این مقاله قصد داریم نگاهی به اپراتور finalize در RxJS بیندازیم.
اپراتور finalize در RxJS برای اجرای دستورالعمل ها هنگام پایان یافتن observable استفاده می شود.
فعال/غیرفعال کردن دکمه ارسال اطلاعات در فرم، هنگام اجرای درخواست HTTP
به مثال زیر که یک نمونه از subscribe کردن یا گوش دادن به یک observable است، دقت کنید:
this.someService.fetchDataFromApi()
.subscribe(
result => {
// success
},
err => {
// some error happened
}
)
فرض کنید کد بالا از طریق کلیک بر روی دکمه ارسال فراخوانی شده است، بعضی از افراد عادت دارند که دو بار بر روی دکمه ها کلیک کنند. ما می خواهیم از فراخوانی مجدد api بک اند بر اثر دوبار کلیک کاربر، جلوگیری کنیم.
اگرچه راه های مختلفی برای این کار وجود دارد اما ما در این آموزش قصد داریم هنگامی که دکمه برای بار اول کلیک شد، آن را غیرفعال کنیم و هنگام پایان یافتن درخواست HTTP آن را دوباره فعال کنیم. به مثال زیر دقت کنید:
this.isLoading = true;
this.someService.fetchDataFromApi()
.subscribe(
result => {
// success
this.isLoading = false;
},
err => {
// some error happened
this.isLoading = false;
}
)
هنگامی که isLoading برابر با true باشد، دکمه ارسال را غیرفعال می کنیم.
همان طور که در مثال بالا می بینید، دستور isLoading = false دوبار تکرار شده، زیرا ما می خواهیم که در هر دو حالت success و error دکمه را فعال کنیم.
گزینه ۱: استفاده از اپراتور tap
همان طور که در مثال زیر می بینید، یکی از گزینه ها می تواند اپراتور tap باشد:
this.isLoading = true;
this.someService.fetchDataFromApi()
.pipe(
tap(_ => {
this.isLoading = false;
})
)
.subscribe(
result => {
// success
},
err => {
// some error happened
}
)
دستورالعمل های نوشته شده در اپراتور tap فقط در حالت success اجرا می شود و در حالت هایی که خطا رخ می دهد یا هنگام terminate (پایان یافتن) observable، دستور this.isLoading = false; اجرا نمی شود. (مانند درخواست های HTTP ناموفق در انگولار)
اگرچه، اپراتور tap به ما این قابلیت را می دهد که دستورالعمل ها را در وضعیت های next، error و complete نیز اجرا کنیم مانند حالتی که در subscribe این وضعیت ها را کنترل می کنیم.
به مثال زیر توجه کنید:
this.someService.fetchDataFromApi()
.pipe(
tap({
next: (x) => {
console.log('tap success', x);
this.isLoading = false;
},
error: (err) => {
console.log('tap error', err);
this.isLoading = false;
},
complete: () => console.log('tap complete')
}),
)
.subscribe(x => {
console.log('Got result', x);
}, (err) => {
console.error('Got error', err);
})
گزینه ۲: استفاده از اپراتور finalize در RxJS
یک گزینه دیگر استفاده از اپراتور finalize می باشد که شبیه ساختار try-catch-finally در زبان های بر پایه C می باشد.
بنابراین می توانیم مثال خود را به شکل زیر تغییر دهیم:
this.isLoading = true;
this.someService.fetchDataFromApi()
.pipe(
finalize(() => {
this.isLoading = false;
})
)
.subscribe(
result => {
// success
},
err => {
// some error happened
}
)
چگونه finalize کار می کند؟
درواقع اپراتور finalize از طریق subscription.add(fn) یک callback برای اجرا هنگام teardown یا از بین رفتن observable تعریف می کند.
نتیجه گیری
توجه کنید که اپراتور finalize زمانی که observable پایان می یابد، اجرا می شود. این نکته بسیار مهم است. این روش برای مواقعی که از Angular HTTP استفاده می کنیم، به خوبی کار می کند. به خاطر این که Observable هایی که توسط سرویس Angular HTTP بازگردانده می شوند، پس از اجرای درخواست HTTP، کامل می شوند.
اما در صورت استفاده از Observable های سفارشی (custom) ممکن است اینگونه نباشد.














دیدگاه بگذارید