angular - 有没有办法一次分派一个动作?
问题描述
细节
我一直在从事一个从 API 获取数据的项目。为了获取这些数据,我将我需要的东西存储在商店中。例如,在商店中,我正在存储当前选择的时间段、地图的当前 bbox 以及从 API 获取的数据。我需要实现的是每次选择的时段或地图的当前边界框发生变化时更新存储中的数据。
为此,我为 Periods、BBox 和 Stats 创建了一个 Action、一个 Reducer 和一个 Effect。我遵循的逻辑如下,我也将它用于 BBox 和 Stats。
代码
export interface IPeriodState {
periods: Period[];
isLoading: boolean;
error: Error;
}
在减速器中,我只是改变状态,仅此而已。我的行为在这一点上是相同的逻辑:
import { Action } from "@ngrx/store";
import { Period } from "../../models/Period";
export enum PeriodActionTypes {
ADD_PERIOD = "[Period] Add Period",
ADD_PERIOD_SUCCESS = "[Period] Add Period Success",
ADD_PERIOD_FAILURE = "[Period] Add Period Failure",
REMOVE_PERIOD = "[Period] Remove Period",
REMOVE_PERIOD_SUCCESS = "[Period] Remove Period Success",
REMOVE_PERIOD_FAILURE = "[Period] Remove Period Failure",
UPDATE_PERIOD = "[Period] Update Period",
UPDATE_PERIOD_SUCCESS = "[Period] Update Period Success",
UPDATE_PERIOD_FAILURE = "[Period] Update Period Failure"
}
// Add Period
export class AddPeriodAction implements Action {
readonly type = PeriodActionTypes.ADD_PERIOD;
constructor(public payload: Period) {}
}
export class AddPeriodSuccessAction implements Action {
readonly type = PeriodActionTypes.ADD_PERIOD_SUCCESS;
constructor(public payload: Period) {}
}
export class AddPeriodFailureAction implements Action {
readonly type = PeriodActionTypes.ADD_PERIOD_FAILURE;
constructor(public error: Error) {}
}
// Remove Period
export class RemovePeriodAction implements Action {
readonly type = PeriodActionTypes.REMOVE_PERIOD;
constructor(public id: string) {}
}
export class RemovePeriodSuccessAction implements Action {
readonly type = PeriodActionTypes.REMOVE_PERIOD_SUCCESS;
constructor(public id: string) {}
}
export class RemovePeriodFailureAction implements Action {
readonly type = PeriodActionTypes.REMOVE_PERIOD_FAILURE;
constructor(public error: Error) {}
}
// Update Period
export class UpdatePeriodAction implements Action {
readonly type = PeriodActionTypes.UPDATE_PERIOD;
constructor(public id: string, public payload: Period) {}
}
export class UpdatePeriodSuccessAction implements Action {
readonly type = PeriodActionTypes.UPDATE_PERIOD_SUCCESS;
constructor(public id: string, public payload: Period) {}
}
export class UpdatePeriodFailureAction implements Action {
readonly type = PeriodActionTypes.UPDATE_PERIOD_FAILURE;
constructor(public error: Error) {}
}
export type PeriodActions =
| AddPeriodAction
| AddPeriodSuccessAction
| AddPeriodFailureAction
| RemovePeriodAction
| RemovePeriodSuccessAction
| RemovePeriodFailureAction
| UpdatePeriodAction
| UpdatePeriodSuccessAction
| UpdatePeriodFailureAction;
实际上,我正在调度多个动作。例如:
//imports omitted
@Injectable()
export class PeriodEffect {
constructor(private actions: Actions) {}
@Effect() addPeriod$ = this.actions.pipe(
ofType<PeriodActions>(PeriodActionTypes.ADD_PERIOD),
mergeMap((action: AddPeriodAction) => [
new AddPeriodSuccessAction(action.payload),
new LoadStatsAction()
]),
catchError(error => of(new AddPeriodFailureAction(error)))
);
@Effect() removePeriod$ = this.actions.pipe(
ofType<PeriodActions>(PeriodActionTypes.REMOVE_PERIOD),
mergeMap((action: RemovePeriodAction) => [
new RemovePeriodSuccessAction(action.id),
new LoadStatsAction()
]),
catchError(error => of(new RemovePeriodFailureAction(error)))
);
@Effect() updatePeriod$ = this.actions.pipe(
ofType<PeriodActions>(PeriodActionTypes.UPDATE_PERIOD),
mergeMap((action: UpdatePeriodAction) => [
new UpdatePeriodSuccessAction(action.id, action.payload),
new LoadStatsAction()
]),
catchError(error => of(new UpdatePeriodFailureAction(error)))
);
}
问题
我的问题是我LoadStatsAction
多次派送,因为每次网站发生变化时,我都需要在商店中获取新数据。让我们看看我的period-selector
组件。一旦期间发生变化,我将使用以下代码管理此更改:
constructor(private moment: MomentPipe, private store: Store<AppState>) {
this.currentPeriod = new Period(
id(),
new Date(2017, 9, 1),
new Date(2018, 9, 1)
);
this.store.dispatch(new AddPeriodAction(this.currentPeriod));
}
ngOnInit() {}
ngOnDestroy() {
this.store.dispatch(new RemovePeriodAction(this.currentPeriod.id));
}
updateCurrentPeriod(period: IPeriod) {
this.currentPeriod._minDate = period.minDate;
this.currentPeriod._maxDate = period.maxDate;
this.store.dispatch(
new UpdatePeriodAction(this.currentPeriod.id, this.currentPeriod)
);
}
概括
有没有办法摆脱多个分派的动作?
笔记
解决方案
我建议提取何时调度LoadStatsAction
动作的逻辑以避免重复代码,它应该如下所示:
@Effect() addPeriod$ = this.actions.pipe(
ofType<PeriodActions>(PeriodActionTypes.ADD_PERIOD),
map((action: AddPeriodAction) => new AddPeriodSuccessAction(action.payload)),
catchError(error => of(new AddPeriodFailureAction(error)))
);
@Effect() removePeriod$ = this.actions.pipe(
ofType<PeriodActions>(PeriodActionTypes.REMOVE_PERIOD),
map((action: RemovePeriodAction) => new RemovePeriodSuccessAction(action.id)),
catchError(error => of(new RemovePeriodFailureAction(error)))
);
@Effect() updatePeriod$ = this.actions.pipe(
ofType<PeriodActions>(PeriodActionTypes.UPDATE_PERIOD),
map((action: UpdatePeriodAction) => new UpdatePeriodSuccessAction(action.id, action.payload)),
catchError(error => of(new UpdatePeriodFailureAction(error)))
);
@Effect() loadStats$ = this.actions.pipe(
ofType(
AddPeriodSuccessAction,
RemovePeriodSuccessAction,
UpdatePeriodSuccessAction
),
mapTo(new LoadStatsAction())
)
现在您可以专注于减少LoadStatsAction
调度、使用debounceTime(x)
或的次数throttleTime(x)
(这些运算符之间的区别可以在这里找到)
推荐阅读
- c++ - 为什么在 boost 图形库的访问者中使用 CRTP 模式?
- ios - UICollectionView scrollToItem 在 iOS 14 中不起作用
- javascript - 如何解决 - 在同一渲染树中发现重复的插槽“默认”存在
- python - Matplotlib - Python 无法每月显示次要刻度标签
- javascript - 如何在 rivetsJS 中使用 OR 条件
- octobercms - 将 slug 添加到用户(RainLab)OctoberCms
- xcode - 如何修复 Xcode 中显示为红色的库?
- vuetify.js - Vuetify 中单独文本字段的标签
- javascript - Javascript 问题
- django - django 数据库缓存不存储值