0

我在 Angular 应用中有 redux 状态:

export interface UIAction {
  name: string;
  isActive: boolean;
}
    
export interface IUIState {
  actions: UIAction[];
}

我已经构建了一个角度服务,它订阅状态并将每个操作的主题存储在 Map 中,并为对某个操作的 isActive-value 感兴趣的调用者返回该主题。是这样的:

public getIsActive$(name: string): Observable<boolean> {  
  let sub = this.subsMap.get(name);
  return sub.asObservable();
}

现在我想更改代码并摆脱所有主题的 Map 并执行以下操作:

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} ]

但是,订阅不会写入控制台,因为它没有订阅“取消”操作的更改。

然后我发送另一个 redux 状态更改(这里只有值):

{ name: 'Save', isActive: true }

并且 UIState.actions 更改为:

[ { name: 'Save', isActive: true}, { name: 'Cancel', isActive: false} ]

现在订阅写入控制台:

Value: true

因为它订阅了“保存”操作的更改。

4

2 回答 2

1

希望我能正确理解这个要求。您可以将自定义函数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。如果任一属性与其先前的值不匹配,它将发出新值。
  • 现在我们有了新值,返回isActive布尔值。
于 2021-08-11T05:01:17.230 回答
0

如果有人对此感兴趣,我就是这样做的。感谢其他人指出我正确的方向:

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));
}
于 2021-08-18T10:25:57.320 回答