详细信息
我一直在从事从API获取数据的项目。为了获取这些数据,我将需要的东西存储在商店中。 例如,在商店中,我正在存储当前选择的时间段,地图的当前bbox以及正在从API中获取的数据。我需要实现的是,每当选定时期或地图的当前边界框发生变化时,都要更新商店中的数据。
为此,我为周期,BBox和统计创建了一个动作,一个减速器和一个效果。我遵循的逻辑如下,我也将其用于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)
);
}
摘要
是否有办法消除多个已分派的动作?
注意
答案 0 :(得分:2)
我建议提取何时分派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)
(可以在here中找到这些运算符之间的区别)
答案 1 :(得分:1)
如果我的问题没错,我想的问题是您想多次分发动作,但又不想将其添加到这3种效果中吗?在这种情况下,您可以执行以下操作:
我们可以在// The Employee now takes an Employee or Employee-like object
// instead of separate arguments.
class Employee {
constructor({ name, gender, department, yy, email, skills }) {
this.name = name;
this.gender = gender;
this.department = department;
this.email = email;
this.skills = skills || [];
}
addNewSkill(skill){
this.skills.push(skill);
}
}
// Create an Employee.
const employee = new Employee({
name: "John Doe",
gender: "male",
department: "CS",
email: "john@doe.com"
});
// Add a skill.
employee.addNewSkill("coding");
// Turn employee to string and save to localStorage.
localStorage.setItem("employee", JSON.stringify(employee));
// Parse the string back into an Employee-like object and
// use that object to construct a new Employee.
const retrievedEmployee = new Employee(JSON.parse(localStorage.getItem("employee")))
// Add another skill, using the Employee instance method.
retrievedEmployee.addNewSkill("reading");
// Logs Employee having 2 skills, one added *before* we saved to localStorage
// and another skill we added *after* we retrieved him from localStorage.
console.log(retrievedEmployee);
运算符中侦听多个动作,在当前请求尚未满足时,使用ofType
或switchMap
取消多个请求。
exhaustMap