StoreItem
클래스에는 두 개의 값(amount
, status
)이 있습니다. 한 값을 변경했을 때 다른 값을 함께 변경하고 싶다면 어떻게 하는 게 좋을까요?
StoreItemA
:setAmount()
내에서 변경한다StoreItemB
: Observable을 사용해서 업데이트하자
import { BehaviorSubject, filter, switchMap, tap, withLatestFrom } from "rxjs"; | |
enum Status { | |
NO_SALE = "NO_SALE", | |
SALE = "SALE" | |
} | |
// 규칙: amount를 0 이하로 변경하면 status를 NO_SALE로 바꿔야 한다 | |
// 규칙: status를 SALE로 변경할 때 amount가 0 이하이면 1로 바꿔야 한다 | |
abstract class StoreItemBase { | |
protected _statusSubject = new BehaviorSubject(Status.NO_SALE); | |
protected _amountSubject = new BehaviorSubject(0); | |
get status$() { | |
return this._statusSubject.asObservable(); | |
} | |
get amount$() { | |
return this._amountSubject.asObservable(); | |
} | |
abstract setStatus(status: Status): void; | |
abstract setAmount(amount: number): void; | |
} | |
// 규칙 체크를 setAmount(), setStatus() 내에서 수행 | |
class StoreItemA extends StoreItemBase { | |
setStatus(status: Status) { | |
this._statusSubject.next(status); | |
if (status === Status.SALE && this._amountSubject.value <= 0) { | |
this._amountSubject.next(1); | |
} | |
} | |
setAmount(amount: number) { | |
this._amountSubject.next(amount); | |
if (amount <= 0) { | |
this._statusSubject.next(Status.NO_SALE); | |
} | |
} | |
} | |
// 조건 체크를 observable 내에서 수행 | |
class StoreItemB extends StoreItemBase { | |
constructor() { | |
super(); | |
this.amount$.pipe( | |
filter((amount) => amount <= 0), | |
tap(() => this.setStatus(Status.NO_SALE)) | |
).subscribe(); | |
this.status$.pipe( | |
filter((status) => status === Status.SALE), | |
withLatestFrom(this.amount$), | |
filter(([, amount]) => amount <= 0), | |
tap(() => this.setAmount(1)) | |
).subscribe(); | |
} | |
setStatus(status: Status) { | |
this._statusSubject.next(status); | |
} | |
setAmount(amount: number) { | |
this._amountSubject.next(amount); | |
} | |
} |