שימוש ב-RXJS

כאשר יש לנו שימוש חוזר בקומפוננטות, או שאנחנו צריכים מידע משותף במקומות שונים בקוד, אנחנו משתמשים בשירותי ה-servuce על מנת שיחזיק משתנים גלובלים עם מידע.

הבעיה היא, שקומפוננטה יכולה לשנות את ערך המשתנה הגלובלי, אבל שאר הקומפוננטות לא יקבלו את הערך המעודכן, אלא אם נבצע בהן איזה פעולה שמעדכנת את הערך. אנחנו רוצים שבכל פעם שישתנה הערך, כל מי שמשתמש בערך הזה יתעדכן בעצמו.

סוג המשתנה המתאים לעבודה של עדכון בין services או בין קומפוננטות הוא Subject.

שימוש ב-subject לשיתוף מידע

קובץ counter.service.ts

export class CounterService {
    counterSubject = new Subject<number>();
    counterValue = 0;

    constructor(){}

    plus(){
        counterValue++;
        this.counterSubject.next(this.counterSubject);
    }

    minus(){
        counterValue--;
        this.counterSubject.next(this.counterSubject);
    }
}

Subject הוא מעין event שכשמגדירים אותו אנחנו אומרים מה יהיה סוג הפרמטר.

אחרי שהגדרנו את המשתנה, נראה מה הפעולות שבהן אני רוצה לדווח על השינוי. במקרה שלנו זה בפעולת plus ופעולת minus. ה-subject זורק לנו את השינוי של הערך.

קובץ counter.component.ts

export class CounterComponent {
    counterValue = 0;
    constructor(private counterService: CounterService) {}

    ngOnInit(){
        this.counterService.counterSubject.subscribe(newCountValue => {
            this.counterValue = newCounterValue;
        });
    }

    plus(){
        this.counterServie.plus();
    }

    minus(){
        this.counterServie.minus();
    }
}

פונקציית subscribe נרשמת לקבלת העדכונים. יש לנו את הערך של counterValue, הוא מבק להתעדכן כל פעם שהערך של ה-counter משתנה. הערך החדש יגיל לכל הקומפוננטות שנרשמו לעדכונים.

הקוד הזה עובד, אבל יש בעיה, יש לנו ב-service משתנים שהם public שכל אחד יכול לגשת אליהם.

קובץ counter.service.ts

export class CounterService {
    private counterSubject = new Subject<number>();
    counterValue = 0;

    get counter$(){
        return this.counterSubject.asObservable();
    }

    constructor(){}

    ...
}

נהפוך את המשתנים ל-private ונגדיר את הפונקציה get counter. היא תחזיר את ה-subject כ-observable. כלומר עם האפשרות לעשות subscribe אבל ללא אפשרות לעשות next.

השימוש בקומפוננטה יהיה:

קובץ counter.component.ts

export class CounterComponent {
    counterValue = 0;
    constructor(private counterService: CounterService) {}

    ngOnInit(){
        this.counterService.counter$.subscribe(newCountValue => {
            this.counterValue = newCounterValue;
        });
    }

    ...
}

שימוש ב-behavior subject

הבעיה בקוד שיש לנו עד כאן היא שאם נוסיף קומפוננטה חדשה עכשיו לעמוד היא תקבל ערך התחלתי מאופס ולא את הערך הנוכחי שיש לנו. נניח שיש לנו משתמש שנכנס לאתר עם שם משתמש וסיסמא, ואנחנו מחזיקים את שם המשתמש כדי להתייחס אליו. אם יגיעו קומפוננטות חדשות, לא יהיה להן את הערך ההתחלתי הזה.

קובץ counter.service.ts

export class CounterService {
    private counterSubject = new BehaviorSubject<number>(0);
    counterValue = 0;

    get counter$(){
        return this.counterSubject.asObservable();
    }

    constructor(){}

    ...
}

ניווט במאמר

מאמרים אחרונים

Weekly Tutorial