انگولار - ngrx: چگونه Observable ها را برای استفاده در async pipe ترکیب کنیم


من دارم سعی میکنم یک نسخهٔ سایهای از تغییرات در حال انتظار با استفاده از observables و ngrx داشته باشم و دارم به یک مشکل کوچک میرسم که نمیفهمم:

export class SearchBoxContainerComponent {
    filterSettings$: Observable<FilterSettings>;
    filterChanges: {[key:string]: any};
    filterChanges$: Subject<{[key:string]: any}>;
    constructor(private store: Store<fromRoot.State>) {
        this.filterChanges = {};
        this.filterChanges$ = new Subject();
        this.filterSettings$ = Observable.combineLatest(
            store.let(fromRoot.getFilterSettings),
            this.filterChanges$,
            (filterSettings, filterChanges) => {
                return Object.assign({}, filterSettings, filterChanges);
            }
        );
        this.filterChanges$.subscribe(foo => {
            console.log('filterChanges$: ', foo);
        });
        this.filterSettings$.subscribe(foo => {
            console.log('filterSettings$: ', foo);
        });
        this.filterChanges$.next(this.filterChanges);
    }

    updateSetting(key, value) {
        this.filterChanges = Object.assign({}, this.filterChanges, {[key]: value});
        this.filterChanges$.next(this.filterChanges);
    }

    submitSearchbox() {
        // TODO send ngrx action to really update the filterSettings
    }
}

اینجا به جای استفاده مستقیم، از Observable.combineLatest استفاده میکنم

this.filterSettings$ = store.let(fromRoot.getFilterSettings); 

برای دریافت یک observable از فروشگاه ngrx.

مشکلی که من دارم این است که وقتی جعبه جستجوی من باز میشود ابتدا همه چیز تهی است. تنها بعد از بهروزرسانی یک مقدار، همه چیز پر میشود. اگر مستقیم آن را با فروشگاه وصل کنم، کار میکند.

من از پایپ async در HTML خود به این شکل استفاده میکنم

<my-component [filterSettings]="filterSettings$ | async"></my-component>

اما این در یک *ngIf است، بنابراین فقط پس از باز شدن جعبه جستجو ارزیابی میشود. حدس من این است که لوله async بعد از اینکه تمام اقدامات انجام شد مشترک میشود و با نبود رویدادهای جدید، مقداری دریافت نمیکند. اما چرا با store.let کار میکند؟ آیا آن یک observable متفاوت است که همیشه مقداری به شما میدهد؟

سؤال این است که من کجا اشتباه میکنم، اینطور به نظر میرسد که هنوز چیزی را از دست دادهام... سوال اضافی: آیا این روش خوبی برای داشتن نسخههای سایهای از دادهها است که میتوان آنها را لغو یا ارسال کرد؟

پاسخ شماره ۱

به جای rxjs/Subject ساده از rxjs/BehaviorSubject استفاده کنید. این مورد آخرین آیتم دریافت شده را به مشترکین جدید ارسال خواهد کرد.

this.filterChanges = {};
this.filterChanges$ = new BehaviorSubject(this.filterChanges);

شما نیازی به استفاده از next() بعد از آن ندارید، زیرا مقدار را در سازنده میگیرد. Observable.combineLatest() تا آن زمان باید همانطور که انتظار میرود عمل کند.