如何获得仅当 属性 值在 redux 状态的对象数组中发生变化时才发出的 Observable?
How to get Observable that emits only when a property value changes in an array of objects in redux state?
我在 angular 应用程序中有 redux 状态:
export interface UIAction {
name: string;
isActive: boolean;
}
export interface IUIState {
actions: UIAction[];
}
我构建了一个 angular 服务,该服务订阅状态并在 Map 中存储每个操作的主题,returns 该主题供对特定操作的 isActive-value 感兴趣的调用者使用.是这样的:
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' */
)));
}
这应该怎么做?下面举个例子。
最初 UIState.actions 看起来像这样:
[ { name: 'Save', isActive: false }, { name: 'Cancel', isActive: true } ]
此时我调用
myService.getIsActive$('Save').subscribe(isActive => {
console.log('Value : ${isActive});
});
然后我发送一个 redux 状态更改(这里只有新值):
{ name: 'Cancel', isActive: false }
UIState.actions 更改为:
[ { name: 'Save', isActive: false }, { name: 'Cancel', isActive: false} ]
但是订阅不会写入控制台,因为它没有订阅 'Cancel' 操作的更改。
然后我发送另一个 redux 状态更改(这里只有值):
{ name: 'Save', isActive: true }
并且 UIState.actions 更改为:
[ { name: 'Save', isActive: true}, { name: 'Cancel', isActive: false} ]
现在订阅写入控制台:
Value: true
因为它订阅了 'Save' 操作的更改。
希望我正确理解了这个要求。对于更复杂的情况,您可以将自定义函数应用于 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()
returns undefined
- 应用检查
name
和 isActive
的自定义函数。如果 属性 与其先前的值不匹配,它将发出新值。
- 现在我们有了新值,return
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));
}
我在 angular 应用程序中有 redux 状态:
export interface UIAction {
name: string;
isActive: boolean;
}
export interface IUIState {
actions: UIAction[];
}
我构建了一个 angular 服务,该服务订阅状态并在 Map 中存储每个操作的主题,returns 该主题供对特定操作的 isActive-value 感兴趣的调用者使用.是这样的:
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' */
)));
}
这应该怎么做?下面举个例子。
最初 UIState.actions 看起来像这样:
[ { name: 'Save', isActive: false }, { name: 'Cancel', isActive: true } ]
此时我调用
myService.getIsActive$('Save').subscribe(isActive => {
console.log('Value : ${isActive});
});
然后我发送一个 redux 状态更改(这里只有新值):
{ name: 'Cancel', isActive: false }
UIState.actions 更改为:
[ { name: 'Save', isActive: false }, { name: 'Cancel', isActive: false} ]
但是订阅不会写入控制台,因为它没有订阅 'Cancel' 操作的更改。
然后我发送另一个 redux 状态更改(这里只有值):
{ name: 'Save', isActive: true }
并且 UIState.actions 更改为:
[ { name: 'Save', isActive: true}, { name: 'Cancel', isActive: false} ]
现在订阅写入控制台:
Value: true
因为它订阅了 'Save' 操作的更改。
希望我正确理解了这个要求。对于更复杂的情况,您可以将自定义函数应用于 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()
returnsundefined
- 应用检查
name
和isActive
的自定义函数。如果 属性 与其先前的值不匹配,它将发出新值。 - 现在我们有了新值,return
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));
}