RxJS’e yakından bakış -3: Scheduler

0 1,721

Merhaba bu yazımda RxJS’in bir diğer bileşenlerinden biri olan Scheduler’den bahsedeceğim. Bu yazı ile, bir sonraki yazımız olan RxJS operatörlerine geçmeden önce RxJS’e çekirdeğinde bulunan tüm konseptlerden bahsetmiş olacağım.

Önceki Bölümler

https://bilisim.io/2019/10/08/rxjse-merhaba-deyin/

https://bilisim.io/2019/10/20/rxjse-yakindan-bakis-1-observables/

https://bilisim.io/2019/11/02/rxjse-yakindan-bakis-2-subjects/

Scheduler Nedir?

Bir aboneliğin(subscription) ne zaman başlayacağını ve bildirimlerin ne zaman yapılacağını kontrol eden yapıdır. Başlamadan önce faydalarından bahsedeyim:

  1. Umulmadık buglardan kurtarır
  2. Yazdığınız kodun yanlış sırada çalışmasını engeller

Makalenin sonunda gerçek hayattan bir örnek vermeye çalışacağım.

Scheduler, üç bileşenden oluşur.

Execution Context: Görevin nerede ve ne zaman çalıştırılacağını (yürütüleceğini) gösterir.

  • Sync Tasks
  • Macro Tasks -> setTimeout()
  • Micro Tasks -> Promise()
  • AnimationFrame -> animationFrame

Execution Policy: Öncelik veya diğer ölçütlere göre görevlerin nasıl saklanacağı ve hangi sırayla alınacağından sorumludur.

Clock: Scheduler’da bulunan now() getter metodu ile zaman kavramını verir. Eğer bir scheduler, belirli bir zamanda bir işlem yapmak durumundaysa zaman kavramına ihtiyacı vardır.

Scheduler, bir observable’ın kendisini dinleyen observer’a hangi yürütme bağlamında(execution context) bildirim göndereceğini tanımlamanıza izin verir.

Aşağıdaki örnekte; 123 değerlerini eş zamanlı olarak yayan bir observable mevcut. Bu değerleri iletmek için kullanılacak eşzamansız programlayıcıyı belirlemek için observeOn operatörü kullanılıyor. https://stackblitz.com/edit/typescript-pzv3t6

Örneğimizde iki tane observable mevcut. İlk observable’a abone olurken observeOn operatörü kullanılmıyor. Konsola yazılan çıktıda herşey eş zamanlı bir şekilde yazılıyor. İkinci observable’da ise observeOn kullanıyor konsol çıktısında eş zamansız olarak değerler görüntüleniyor. Bunun sebebi observeOn(asyncScheduler);new Observable ile Son Observer arasında proxy Observer tanıtmasıdır. Aşağıdaki örnek kodda, bu durum daha anlaşılır bir şekilde gösterilmiştir. https://stackblitz.com/edit/fvbm14

 

observeOn() operatörü gecikme için bir parametre daha alır. Bu parametre ile yayılma işlemi herhangi bir zamana planlanabilir(schedule). Eğer observeOn()operatörüne herhangi bir değer verilmezse varsayılan olarak 0 şeklinde programlanır. Yukarıdaki örneklerde observeOn()operatörüne gecikme parametresi verilmediği için varsayılan olarak 0 olarak alınmıştır. Aşağıdaki örnekte ise abonelik başladıktan üç saniye sonra değerlerin yayılmasını ayarlayan scheduler kullanımı mevuttur. https://stackblitz.com/edit/rxjs-scheduler-kullanimi

Scheduler Türleri

asyncScheduler; RxJs tarafından sunulan built-in scheduler’dir. Aşağıdaki schedulerlerin her biri, Scheduler nesnesinin statik özellikleri kullanılarak oluşturulabilir .

https://stackblitz.com/edit/rxjs-scheduler-kullanimi-neb9zz

Yukarıdaki örnekte gecikme değişkenini 0 yaptığınızda farklı çıktı almaktasınız.

 

Peki bu bilgi gerçek hayatta ne işime yarayacak?

Konuyu daha iyi anlamak için bir örnek yapalım. Aşağıdaki Angular uygulamasındaki hataya bakalım. Uygulama çalıştığında ExpressionChangedAfterItHasBeenCheckedError hatası alınmaktadır. Hatanın çözümü için üç farklı yöntem gösterilecektir. Üçüncü yöntem RxJS Scheduler ile yapılmıştır. https://stackblitz.com/edit/angular-owpbyp

 

Bu hata ne zaman ortaya çıkar

  1. Eğer kodunuzda AfterViewInit yaşam döngüsü kancasını(lifecycle hook) kullanıyorsanız, ViewChild, AfterViewInit çağrılana kadar tanımsızdır.
  2. DOM’u doğrudan değiştiriyorsanız, Angular değişiklikleri tespit edemez ve doğru reaksiyon veremez.
  3. HTML şablonunuzun içerisinde fonksiyon çağırıyorsanız race condition durumunun ortaya çıkmasında meydana gelir

Bu hatadan kurtulmak için;

  1. ngAfterViewInit içersinde setTimeout kullanılabilir. https://stackblitz.com/edit/angular-zjxnbh

2. Change Detection kullanılarak bu sorun çözülebilir. https://stackblitz.com/edit/angular-rhtgfb

3. RxjS ile daha şık bir işlem ile çözülebilir.  https://stackblitz.com/edit/angular-mjqtms

 

`asyncScheduler kullanırsanız; scheduler metoduna verilen callback fonksiyonu ()=> { this.name = 'foo';}setTimeout gibi varsayılan değerde eşzamansız olarak yürütülür. Sonuc olarak; bir adet makro görev zamanlanmış oldu.

Konuyla ilgili olarak aşağıdaki videoyu tavsiye ederim

Kaynak

 

 

 

Email adresiniz yayınlanmayacaktır.