Как получить Observable, который излучает только тогда, когда значение свойства изменяется в массиве объектов в состоянии redux?
У меня есть состояние редукции в угловом приложении:
export interface UIAction {
name: string;
isActive: boolean;
}
export interface IUIState {
actions: UIAction[];
}
Я создал сервис angular, который подписывается на состояние и сохраняет объекты для каждого действия на карте и возвращает этот объект вызывающим абонентам, которые заинтересованы в значении isActive для определенного действия. Это примерно так:
public getIsActive$(name: string): Observable<boolean> {
let sub = this.subsMap.get(name);
return sub.asObservable();
}
Теперь я хочу изменить код и избавиться от карты со всеми объектами и сделать что-то вроде этого:
public getIsActive$(name: string): Observable<boolean> {
return this.ngRedux.select<IUIState>('ui').pipe(
/* this should use some operators so that
the returned Observable emits only when
UIAction.isActive changes for the action
in question. The action in question is
found from the state.actions-array using
parameter 'name' */
)));
}
Как это сделать?
2 ответа
Надеюсь, я правильно понимаю это требование. Вы можете применить пользовательскую функцию к
distinctUntilChanged()
для более сложных случаев.
public getIsActive$(name: string):Observable<boolean> {
return this.ngRedux.select<IUIState>('ui').pipe(
map(uiState=>uiState.find(state=>state.name===name)),
filter(state=>!!state),
distinctUntilChanged((prev, curr)=>
prev.name===curr.name && prev.isActive === curr.isActive
),
map(state=>state.isActive)
);
}
Вот построчное описание того, что происходит:
- Найдите состояние внутри массива по его имени
- Отфильтровать на случай
.find()
возвращаетсяundefined
- Примените настраиваемую функцию, которая проверяет оба
name
и . Если какое-либо свойство не соответствует своему предыдущему значению, оно выдаст новое значение. - Теперь, когда у нас есть новое значение, вернем
isActive
логическое.
Если кому-то это интересно, я так и сделал. Спасибо за то, что другие указали мне правильное направление:
public getIsActive$(name: UIActionName): Observable<boolean> {
return this.getUIAction$(name).pipe(
map(axn => axn.isActive)).pipe(distinctUntilChanged());
}
private getUIAction$(name: UIActionName): Observable<UIAction> {
return this.ngRedux.select<IUIState>('ui').pipe(map(state => {
return state.actions.find(actn => actn.name === name);
})).pipe(
filter((axn: UIAction | undefined): axn is UIAction => axn !== undefined));
}