Polski frontend

Piotr Kowalski — JavaScript, Front-end oraz Node.js

Angular: Krótka historia o tym jak złamałem system

Lubię krótkie wpisy. Tylko nie umiem ich pisać. Stąd też rzadko publikuję, bo wyobrażam sobie te wielogodzinne poświęcenie, aby napisać WSPANIAŁY, a zaraz długi artykułu traktującego o zadanym temacie…

Muszę nauczyć się pisać zwięźle i z mięsem. Sam lubię czytać takie rzeczy, więc czytelnicy tego bloga zapewne również. Do rzeczy.

Problem

Jest sobie taki serwis:

@Injectable() export class UserPurchasesStateManagerService { private purchasesState$ = new BehaviorSubject(...); public setPurchasesState(state: number): void { this.purchasesState$.next(state); } public getPurchasesState$(): BehaviorSubject<number> { return this.purchasesState$; } }

Niby wszystko poprawnie, ale errrr…​

Wystarczy, że po utworzeniu instancji serwisu (przypominam, że w Angularze instancje serwisów są singletonami) zrobię tak:

// Sztuczne tworzenie, oczywiście Angular zrobi to niejawnie const stateManager = new UserPurchasesStateManagerService(); // Boom!! stateManager.getPurchasesState$().next(null)​;

…i złamałem system ☹️

Solucja

Trzeba zmienić definicję (i sygnaturę) gettera na:

// ... export class UserPurchasesStateManagerService { // ... public getPurchasesState$(): Observable<number> { return this.purchasesState$.asObservable(); } }

A teraz krótka porada:

Porada

Jeśli gdzieś chcemy zwrócić subject-a to lepiej zrobić tak:

ukryć do private-em zrobić getter, który go zwróci ale przekształci za pomocą .asObservable() w strumień read-only inaczej oddamy władzie zmiany stanu komuś innemu.