Useful Built-in Observables

Ye Min Ko
Learn Ng
Published in
3 min readSep 30, 2021
Photo by Abe B. Ryokan on Unsplash

Subject

Event တစ်ခု ဖြစ်ပေါ်လာတိုင်း တစ်ခုခုကို လုပ်စေချင်ရင် Observable မှာ Subject ဆိုတာရှိပါတယ်။ EventEmitter နဲ့အတူတူပါပဲ Subject ကပိုကောင်းတဲ့နည်းလမ်းဖြစ်လို့ အစားထိုးသုံးသင့်ပါတယ်။

အရင်ဆုံး EventEmitter နဲ့စမ်းကြပါမယ်။ UserService ထဲမှာ အခုလိုရေးပါ။

activatedEmitter = new EventEmitter<boolean>();

UsersComponent ထဲမှာ button တစ်ခုထည့်လိုက်ပါ။

HTML
<button class="btn btn-primary" (click)="activate()">Activate Me</button>
TypeScript
activate() {
this.userService.activatedEmitter.emit(true);
}

AppComponent ကနေ subscribe လုပ်ပြီး true ဖြစ်မှ စာပြပေးအောင် ရေးလိုက်ပါ။

HTML
<h1 *ngIf="isActivated">Activated!</h1>
TypeScript
isActivated = false;
ngOnInit() {
this.userService.activatedEmitter.subscribe((didActivate) => {
this.isActivated = didActivate;
});
}

ဒါဆိုရင် button နှိပ်လိုက်တာနဲ့ AppComponent ကသိပြီး စာတန်းပြပေးမှာ ဖြစ်ပါတယ်။

localhost:4200

ဆက်လက်ပြီး EventEmitter နေရာမှာ Subject ဘယ်လိုပြောင်းသုံးမလဲ ကြည့်ရပါမယ်။

UserService ထဲမှာအခုလိုပြင်ပါ။ EventEmitter နေရာမှာ အစားထိုးလိုက်တာ ပါပဲ။

import { Subject } from 'rxjs';activatedEmitter = new Subject<boolean>();

UsersComponent ထဲက emitနေရာမှာ next လိုပြောင်းပေးရပါမယ်။

this.userService.activatedEmitter.next(true);

ဒီလိုပြောင်းလိုက်ယုံနဲ့ နဂိုအတိုင်း ပြန်အလုပ်လုပ်သွားမှာ ဖြစ်ပါတယ်။ Subscribe လုပ်ပြီး အသုံးပြုပြီဆိုရင် memory leak မဖြစ်စေဖို့ ngOnDestroy မှာ unsubscribe လုပ်ဖို့မမေ့ပါနဲ့။ AppComponent မှာ အခုလို ထပ်ထည့်ပါ။

sub: Subscription = new Subscription();ngOnInit() {
this.sub = this.userService.activatedEmitter.subscribe(...);
}
ngOnDestroy() {
this.sub.unsubscribe();
}

Subject က Observable ဖြစ်လို့ Operators တွေနဲ့လည်း တွဲသုံးလို့ ရသွားမှာ ဖြစ်ပါတယ်။ တစ်ခုသတိထားရမှာက @Output နဲ့သုံးတဲ့အခါ EvenEmitter ကိုသာသုံးရမှာဖြစ်ပြီး Subject ကို ပြောင်းသုံးလို့ မရပါ။

BehaviorSubject

Subject နဲ့အတူတူပါပဲ။ ဒါပေမဲ့ BehaviorSubject ရဲ့ထူးခြားချက်က subscribe မလုပ်ခင်ကပြောင်းလဲသွားခဲ့တဲ့ data ကိုရယူနိုင်ခြင်းပဲ ဖြစ်ပါတယ်။

ဆိုလိုတာက Subject သည် emit လုပ်လိုက်တဲ့ data ကိုမသိမ်းထားပါ။ ဒါကြောင့် subscribe မလုပ်ခင်က emit လုပ်လိုက်တဲ့ data ကို subscribe လုပ်သူက လက်ခံရရှိလိုက်မှာ မဟုတ်ပါ။

ဥပမာစမ်းသပ်နိုင်ဖို့ AppComponent မှာအခုလိုရေးပါ။

subject = new Subject<number>();
sub2: Subscription = new Subscription();
testSubject() {
this.subject.next(1);
this.sub2 = this.subject.subscribe((num) => {
console.log('num is : ' + num);
});
this.subject.next(2);
}
ngOnInit() {
this.testSubject();
}
ngOnDestroy() {
this.sub2.unsubscribe();
}

console ကိုကြည့်လိုက်ရင် num is : 2 ပဲထွက်လာတာ တွေ့ရမှာပါ။

Subject test

ဒီလိုဖြစ်ရတာက next(1) ကိုလုပ်ချိန်မှာ Subject ကို subscribe မလုပ်ရသေးတာကြောင့်ဖြစ်ပါတယ်။ next(2) လုပ်ပြီးချိန်မှာတော့ subscribe လုပ်ပြီးပြီဖြစ်လို့ log ထွက်လာတာပဲဖြစ်ပါတယ်။

ဆက်လက်ပြီး BehaviorSubject ကိုစမ်းသပ်ဖို့ AppComponent မှာပဲဆက်ပြီး အောက်ပါ code တွေရေးပါ။

behaviorSubject = new BehaviorSubject<number>(0);
sub3: Subscription = new Subscription();
testBehaviorSubject() {
this.behaviorSubject.next(1);
this.sub3 = this.behaviorSubject.subscribe((num) => {
console.log('[Behaviour] num is : ' + num);
});
this.behaviorSubject.next(2);
}
ngOnInit() {
this.testBehaviorSubject();
}
ngOnDestroy() {
this.sub3.unsubscribe();
}

BehaviorSubject က initial variable တစ်ခု သတ်မှတ်ပေးဖို့ လိုတာကြောင့် 0 ထည့်ထားတာ တွေ့ရမှာပါ။ ရလဒ်ကတော့ အခုလို တွေ့ရမှာပါ။

BehaviorSubject test

1 ရော 2 ပါလက်ခံရရှိတာ တွေ့ရမှာ ဖြစ်ပါတယ်။ ဒါကြောင့် လက်ရှိ data ကိုလည်းလိုချင်တယ် နောက်ထပ် emit လုပ်မဲ့ data ကိုလည်းလိုချင်ရင် BehaviorSubject ကိုသုံးပါ။ လက်ရှိ data ကိုမလိုချင်ပဲ နောက်ထပ် emit လုပ်မဲ့ data အသစ်ကိုပဲ လိုချင်ရင်တော့ Subject ကို အသုံးပြုနိုင်ပါတယ်။

Prevent pushing data to Subjects

Subjects (Subject and BehaviorSubject) တွေက emit လုပ်နိုင်သလို subscribe လည်းလုပ်နိုင်ပါတယ်။ ကိုယ်ရေးထားတဲ့ Subjects ကို subscribe လုပ်ခွင့်ပဲပေးပြီး emit လုပ်ခွင့် မပေးချင်ရင် အခုလို ကာကွယ်ထားလို့ ရပါတယ်။

Subject လေ့လာတုံးက ရေးသားခဲ့တာကိုပဲ ပြုပြင်ပြီး လေ့လာကြပါမယ်။ အရင်ဆုံး UserService မှာအခုလိုပြင်ရေးပါ။

export class UserService {
private activatedEmitter = new Subject<boolean>();
activateObservable = this.activatedEmitter.asObservable();
doActivate() {
this.activatedEmitter.next(true);
}
...
}

နဂိုရေးသားခဲ့တဲ့ Subject ကို private လုပ်လိုက်ပါတယ်။ ဒါကြောင့် service ပြင်ပက access လုပ်လို့ရတော့မှာ မဟုတ်ပါ။ Subject ကို asObservable() သုံးပြီး Observable တစ်ခုအနေနဲ့ ပြောင်းယူလိုက်ပါတယ်။ ဒါကြောင့် ခေါ်သုံးမဲ့သူတွေဟာ activateObservable ကိုပြောင်းခေါ်ပေးရမှာ ဖြစ်သလို subscribe ပဲလုပ်လို့ရတော့မှာလည်း ဖြစ်ပါတယ်။ ဒါကြောင့် emit လုပ်ဖို့အတွက် service ထဲမှာပဲ method တစ်ခုနဲ့ရေးထားလိုက်တာ ဖြစ်ပါတယ်။

ဆက်လက်ပြီး UsersComponent မှာအခုလို ပြင်ပေးပါ။

activate() {
this.userService.doActivate();
}

ပြီးရင်တော့ AppComponent မှာ အောက်ပါအတိုင်း activatedObservable ကို ပြောင်းခေါ်လိုက်ပါ။

ngOnInit() {
this.sub = this.userService.activateObservable.subscribe();
...
}

ရလဒ်ကတော့ အတူတူပဲဖြစ်ပေမဲ့ Subject ကိုတိုက်ရိုက် access လုပ်တာ မဟုတ်တော့ပဲ Observable ကနေသာ access လုပ်ရတော့တာ ဖြစ်လို့ မှားယွင်းပြီး next() ခေါ်မိမှာတွေကို ကာကွယ်ပြီးသား ဖြစ်သွားပါတယ်။

Of

Argument တွေကို observable sequence အဖြစ် ပြောင်းလဲပေးတာ ဖြစ်ပါတယ်။ AppComponent မှာ အခုလို စမ်းနိုင်ပါတယ်။

ngOnInit() {
of('A', 'B', 'C', 'D').subscribe((data) => console.log(data));
of([1, 2, 3]).subscribe((data) => console.log(data));
}

ရလဒ်အနေနဲ့ အခုလို ထွက်လာမှာ ဖြစ်ပါတယ်။ argument တစ်ခုကို emit တစ်ခါလုပ်ပေးတာ တွေ့ရမှာပါ။

rxjs of

From

Observable မဟုတ်တာကို Observable အဖြစ် convert လုပ်ပေးပါတယ်။ Promise ကို Observable ပြောင်းရာမှာ အသုံးများပါတယ်။

ngOnInit() {
from([1, 2, 3]).subscribe((data) => console.log(data));
let asyncTask = new Promise((resolve, reject) => resolve('Hi'));
from(asyncTask).subscribe((data) => console.log(data));
}

ရလဒ်အနေနဲ့ အခုလို ထွက်လာမှာ ဖြစ်ပါတယ်။ Array ကိုထည့်ပေးလိုက်တဲ့အခါ of နဲ့မတူတဲ့ ရလဒ်ကို ထုတ်ပေးတာ သတိပြုပေးပါ။

rxjs from

Previous: Operators

Next: Http Requests

--

--

Ye Min Ko
Learn Ng

🌐 Web Developer | 👀 Self-Learner | 👨‍💻 An Introvert