当另一个动作成功时调度一个动作
Dispatch a Action when the other action is successful
我是 angular 和 redux 世界的新手。我想我有一个常见问题,但我找不到正确的答案,或者我只需要一个有用的提示。我在我的应用程序中使用 ngrx,我想更新用户的一些基本数据。然后我想重新加载一个用户的数据。
简而言之
(1) 更新用户数据
(2)加载用户数据
(3) 在前端可视化
如果我先调度更新然后加载数据,它并不总是有效。我了解到调度程序是异步运行的,因此不能说哪个先完成。
我的想法。我将不得不 (1) 使用承诺更新用户数据,然后 (2) 加载和显示用户数据。还是我错了?
感谢您的帮助
这是我的代码
currenUser.effects.ts
[...]
@Injectable()
export class CurrentUserEffects {
constructor(
private actions$: Actions,
private currentUserService: CurrentUserService
) {}
@Effect()
loadCurrentUser$ = this.actions$.pipe(
ofType(ActionTypes.LoadCurrentUser),
mergeMap((action: LoadCurrentUserAction) =>
this.currentUserService
.getCurrentUserNew()
.pipe(
map(
(currentUser: CurrentUserNew) => new LoadCurrentUserActionFinished(currentUser)
)
)
)
);
@Effect()
updateCurrentUser$ = this.actions$.pipe(
ofType(ActionTypes.UpdateCurrentUser),
switchMap((action: UpdateCurrentUserAction) =>
// update
this.currentUserService
.updateCurrentUser(action.oldCurrentuser, action.newCurrentUser)
.then(
response => {
return new UpdateCurrentUserActionFinished(response);
}
)
// here relaod data?
)
);
}
currentUser.actions.ts
import { CurrentUserNew } from './../../models/currentUserNew';
import { Action } from '@ngrx/store';
export enum ActionTypes {
LoadCurrentUser = '[CurrentUser] Load current user',
LoadCurrentUserFinished = '[CurrentUser] Load current user finished',
UpdateCurrentUser = '[CurrentUser] Update current user',
UpdateCurrentUserFinished = '[CurrentUser] Update current user finished',
}
export class LoadCurrentUserAction implements Action {
readonly type = ActionTypes.LoadCurrentUser;
}
export class LoadCurrentUserActionFinished implements Action {
readonly type = ActionTypes.LoadCurrentUserFinished;
constructor(public payload: CurrentUserNew) {}
}
export class UpdateCurrentUserAction implements Action {
readonly type = ActionTypes.UpdateCurrentUser;
constructor(
public oldCurrentuser: CurrentUserNew,
public newCurrentUser: CurrentUserNew
) {}
}
export class UpdateCurrentUserActionFinished implements Action {
readonly type = ActionTypes.UpdateCurrentUserFinished;
constructor(public payload: boolean) {}
}
export type CurrentUserActions =
| LoadCurrentUserAction
| LoadCurrentUserActionFinished
| UpdateCurrentUserAction
| UpdateCurrentUserActionFinished;
currentUser.reducer.ts
import { CurrentUserNew } from './../../models/currentUserNew';
import { CurrentUserActions, ActionTypes } from './currentUser.actions';
export interface ReducerCurrentUserState{
currentUser: CurrentUserNew;
isUpdated: boolean;
}
export const initialState: ReducerCurrentUserState = {
currentUser: null,
isUpdated: false
};
export function currentUserReducer(
state = initialState,
action: CurrentUserActions
): ReducerCurrentUserState {
switch (action.type) {
case ActionTypes.LoadCurrentUser: {
return {
...state,
};
}
case ActionTypes.LoadCurrentUserFinished: {
return {
...state,
currentUser: action.payload,
};
}
case ActionTypes.UpdateCurrentUser: {
return {
...state,
};
}
case ActionTypes.UpdateCurrentUserFinished: {
return {
...state,
isUpdated: action.payload,
};
}
default:
return state;
}
}
currentUser.selectors.ts
import { ReducerCurrentUserState, currentUserReducer } from './currentUser.reducer';
import { ActionReducerMap, createFeatureSelector, createSelector } from '@ngrx/store';
export const currentUserFeatureStateName = 'currentUserFeature';
export interface CurrentUserState {
currentUser: ReducerCurrentUserState;
}
export const currentUserReducers: ActionReducerMap<CurrentUserState> = {
currentUser: currentUserReducer,
};
// extract the main property from the state object
export const getCurrentUserFeatureState = createFeatureSelector<CurrentUserState>(
currentUserFeatureStateName
);
export const getCurrentUser = createSelector(
getCurrentUserFeatureState,
(state: CurrentUserState) => state.currentUser.currentUser
)
export const isCurrentUserUpdatedSuccessful = createSelector(
getCurrentUserFeatureState,
(state: CurrentUserState) => state.currentUser.isUpdated
)
起初我尝试在一个效果中调用两个动作
@Effect()
updateAndLoadCurrentUser$ = this.actions$.pipe(
ofType(ActionTypes.UpdateAndLoadCurrentUser),
switchMap((action: UpdateCurrentUserAction) =>
of(
new UpdateCurrentUserAction(action.oldCurrentuser, action.newCurrentUser),
new LoadCurrentUserAction(),
new UpdateAndLoadCurrentUserActionFinished()
)
)
);
这里是异步动作值得我回答的问题。
我的解决方案:
实际上我的解决方案是调用一个动作。该操作向后端调用 http 请求,后端为我提供了正确的对象。
但是,我现在对如何一个接一个地触发两个动作感兴趣。不幸的是我还没有找到解决方案
我是 angular 和 redux 世界的新手。我想我有一个常见问题,但我找不到正确的答案,或者我只需要一个有用的提示。我在我的应用程序中使用 ngrx,我想更新用户的一些基本数据。然后我想重新加载一个用户的数据。
简而言之 (1) 更新用户数据 (2)加载用户数据 (3) 在前端可视化
如果我先调度更新然后加载数据,它并不总是有效。我了解到调度程序是异步运行的,因此不能说哪个先完成。
我的想法。我将不得不 (1) 使用承诺更新用户数据,然后 (2) 加载和显示用户数据。还是我错了?
感谢您的帮助
这是我的代码
currenUser.effects.ts
[...]
@Injectable()
export class CurrentUserEffects {
constructor(
private actions$: Actions,
private currentUserService: CurrentUserService
) {}
@Effect()
loadCurrentUser$ = this.actions$.pipe(
ofType(ActionTypes.LoadCurrentUser),
mergeMap((action: LoadCurrentUserAction) =>
this.currentUserService
.getCurrentUserNew()
.pipe(
map(
(currentUser: CurrentUserNew) => new LoadCurrentUserActionFinished(currentUser)
)
)
)
);
@Effect()
updateCurrentUser$ = this.actions$.pipe(
ofType(ActionTypes.UpdateCurrentUser),
switchMap((action: UpdateCurrentUserAction) =>
// update
this.currentUserService
.updateCurrentUser(action.oldCurrentuser, action.newCurrentUser)
.then(
response => {
return new UpdateCurrentUserActionFinished(response);
}
)
// here relaod data?
)
);
}
currentUser.actions.ts
import { CurrentUserNew } from './../../models/currentUserNew';
import { Action } from '@ngrx/store';
export enum ActionTypes {
LoadCurrentUser = '[CurrentUser] Load current user',
LoadCurrentUserFinished = '[CurrentUser] Load current user finished',
UpdateCurrentUser = '[CurrentUser] Update current user',
UpdateCurrentUserFinished = '[CurrentUser] Update current user finished',
}
export class LoadCurrentUserAction implements Action {
readonly type = ActionTypes.LoadCurrentUser;
}
export class LoadCurrentUserActionFinished implements Action {
readonly type = ActionTypes.LoadCurrentUserFinished;
constructor(public payload: CurrentUserNew) {}
}
export class UpdateCurrentUserAction implements Action {
readonly type = ActionTypes.UpdateCurrentUser;
constructor(
public oldCurrentuser: CurrentUserNew,
public newCurrentUser: CurrentUserNew
) {}
}
export class UpdateCurrentUserActionFinished implements Action {
readonly type = ActionTypes.UpdateCurrentUserFinished;
constructor(public payload: boolean) {}
}
export type CurrentUserActions =
| LoadCurrentUserAction
| LoadCurrentUserActionFinished
| UpdateCurrentUserAction
| UpdateCurrentUserActionFinished;
currentUser.reducer.ts
import { CurrentUserNew } from './../../models/currentUserNew';
import { CurrentUserActions, ActionTypes } from './currentUser.actions';
export interface ReducerCurrentUserState{
currentUser: CurrentUserNew;
isUpdated: boolean;
}
export const initialState: ReducerCurrentUserState = {
currentUser: null,
isUpdated: false
};
export function currentUserReducer(
state = initialState,
action: CurrentUserActions
): ReducerCurrentUserState {
switch (action.type) {
case ActionTypes.LoadCurrentUser: {
return {
...state,
};
}
case ActionTypes.LoadCurrentUserFinished: {
return {
...state,
currentUser: action.payload,
};
}
case ActionTypes.UpdateCurrentUser: {
return {
...state,
};
}
case ActionTypes.UpdateCurrentUserFinished: {
return {
...state,
isUpdated: action.payload,
};
}
default:
return state;
}
}
currentUser.selectors.ts
import { ReducerCurrentUserState, currentUserReducer } from './currentUser.reducer';
import { ActionReducerMap, createFeatureSelector, createSelector } from '@ngrx/store';
export const currentUserFeatureStateName = 'currentUserFeature';
export interface CurrentUserState {
currentUser: ReducerCurrentUserState;
}
export const currentUserReducers: ActionReducerMap<CurrentUserState> = {
currentUser: currentUserReducer,
};
// extract the main property from the state object
export const getCurrentUserFeatureState = createFeatureSelector<CurrentUserState>(
currentUserFeatureStateName
);
export const getCurrentUser = createSelector(
getCurrentUserFeatureState,
(state: CurrentUserState) => state.currentUser.currentUser
)
export const isCurrentUserUpdatedSuccessful = createSelector(
getCurrentUserFeatureState,
(state: CurrentUserState) => state.currentUser.isUpdated
)
起初我尝试在一个效果中调用两个动作
@Effect()
updateAndLoadCurrentUser$ = this.actions$.pipe(
ofType(ActionTypes.UpdateAndLoadCurrentUser),
switchMap((action: UpdateCurrentUserAction) =>
of(
new UpdateCurrentUserAction(action.oldCurrentuser, action.newCurrentUser),
new LoadCurrentUserAction(),
new UpdateAndLoadCurrentUserActionFinished()
)
)
);
这里是异步动作值得我回答的问题。
我的解决方案:
实际上我的解决方案是调用一个动作。该操作向后端调用 http 请求,后端为我提供了正确的对象。
但是,我现在对如何一个接一个地触发两个动作感兴趣。不幸的是我还没有找到解决方案