我已按照这种方法https://stackblitz.com/edit/facades-with-rxjs-only?file=src%2Fapp%2Fuser.facade.ts在NG应用中通过服务来组织状态管理。我遇到state$
可观察到的问题,该问题仅将initialExpensesState
的值传递给BehaviorSubject
并发出一次,而addExpensesGroup
方法按预期为BehaviorSubject
状态设置了新值,但没有从state$
以及expenseGroups$
和其他派生的Observable发出的值:
@Injectable()
export class ExpensesService {
projectId$;
private store = new BehaviorSubject<ExpensesState>(initialExpensesState);
private state$ = this.store.asObservable().pipe(
tap(r => console.log('emitted value', r)), // => emits only once with initial value initialExpensesState
distinctUntilChanged()
);
get expensesState(): ExpensesState {
return this.store.getValue();
}
set expensesState(val: ExpensesState) {
this.store.next(val);
}
expenseGroups$ = this.state$.pipe(map(state => state.expenseGroups),
tap(r => console.log('expenseGroups$', r)), // emits only once with initial value initialExpensesState
distinctUntilChanged());
errorMessage$ = this.state$.pipe(map(state => state.errorMessage),
tap(r => console.log(' errorMessage$', r)), // emits only once
distinctUntilChanged())
isLoading$ = this.state$.pipe(map(state => state.isLoading));
vm$: Observable<ExpensesState> = Observable.combineLatest(this.expenseGroups$, this.errorMessage$, this.isLoading$).pipe(
map(([expenseGroups, errorMessage, isLoading]) => ({ expenseGroups, errorMessage, isLoading }))
);
constructor(
private http: HttpClient,
private appService: AppService,
private route: ActivatedRoute
) {
this.projectId$ = this.route.params.pipe(
map(({ id }) => id),
tap(r => console.log('response1', r)));
Observable.combineLatest(this.projectId$, this.expenseGroups$).pipe(
tap(r => console.log('response', r)), // emits only once
switchMap(([projectId]) => this._getExpenseGroups(projectId))
).subscribe(expenseGroups => {
this.expensesState = { ...this.expensesState, expenseGroups, isLoading: false}
})
}
addExpensesGroup() {
return this.http
.get(this.appService.getBaseUrl()+'/api/template/group')
.subscribe(response => {
const group = {
models: response['models'],
isNew: true
};
this.expensesState = {
...this.expensesState,
expenseGroups: [group, ...this.expensesState.expenseGroups],
}) // set new value for `BehaviorSubject` as expected
console.log('expensesState',this.expensesState) // new state set but state$ did not trigger with new value
})
}
_getExpenseGroups(projectId): Observable<any> {
return this.http.get(this.appService.getBaseUrl() + `/api/expenses/groups/${projectId}`)
}