در این مقاله قصد داریم نگاهی به اپراتور 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) ممکن است اینگونه نباشد.
دیدگاه بگذارید