我在第二次或更多次调度登录操作时遇到问题。对于第一个请求,如果登录成功,则可以进行evrything,并且可以将用户重新路由到主页。如果未成功,您将收到一条消息,指出您的登录错误,应该重试,但是如果第二次尝试登录,则不会发送任何请求。
单击按钮“登录”后调用的方法是类“ AccountLoginComponent”中的onLogin方法。
减速器
import {createEntityAdapter, EntityAdapter, EntityState} from '@ngrx/entity';
import {ActionListModel} from '../models/actionListModel';
import {ActionDetailModel} from '../models/actionDetailModel';
import {createReducer, on} from '@ngrx/store';
import * as ActionActions from './action.actions';
export interface ActionState extends EntityState<ActionListModel> {
actionDetail: ActionDetailModel,
messageActionCreation: string,
actionDetailStatus: string,
actionListStatus: string,
actionCreationStatus: string,
}
export function selectActionId(action: ActionListModel): number {
//In this case this would be optional since primary key is id
return action.idAction;
}
// we will add entity adapter to our init state
export const adapter: EntityAdapter<ActionListModel> = createEntityAdapter<ActionListModel>({
selectId: selectActionId
});
// our init state is init state of EntityState
export const initialState: ActionState = {
...adapter.getInitialState(),
actionDetail: null,
messageActionCreation: "",
actionListStatus: "",
actionDetailStatus: "",
actionCreationStatus: "",
};
const _actionReducer = createReducer(
initialState,
on(ActionActions.loadActionsPageSuccess, (state, {actionInList}) => {
return adapter.addAll(actionInList, state);
}),
on(ActionActions.loadActionsPageSuccess, (state, {status}) => ({
...state, actionListStatus: status
})),
on(ActionActions.loadActionDetailSuccess, (state, {actionDetail}) => ({
...state, actionDetail: actionDetail, actionDetailStatus: status
})),
on(ActionActions.createAirsoftActionSuccess, (state, {action, status}) => ({
...state, actionDetail: action, actionCreationStatus: status,
}))
);
export function actionReducer(state, action) {
return _actionReducer(state, action);
}
// get the selectors
const {
selectIds,
selectEntities,
selectAll,
selectTotal,
} = adapter.getSelectors();
export const selectActionIds = selectIds;
export const selectActionsEntities = selectEntities;
export const selectAllActions = selectAll;
export const selectActionsTotal = selectTotal;
动作
import {createAction, props} from '@ngrx/store';
import {AccountModel} from '../models/account.model';
export enum AccountActionsTypes {
AccountLogin = '[Login Page] Account Login',
AccountLoginSuccess = '[Login Page] Account Login Success',
AccountLoginFailed = '[Login Page] Account Login Failed',
AccountLogout = '[Header] Account Logout',
AccountActivation = '[Activation page] Account Activation',
AccountActivationSuccess = '[Activation page] Account Activation Success',
AccountActivationFailed = '[Activation page] Account Activation Failed',
}
export const login = createAction(AccountActionsTypes.AccountLogin, props<{ email: string; password: string }>());
export const loginSuccess = createAction(AccountActionsTypes.AccountLoginSuccess, props< { account : AccountModel, token : string, message: string, status: string}>());
export const loginFailed = createAction(AccountActionsTypes.AccountLoginFailed);
export const logout = createAction(AccountActionsTypes.AccountLogout);
export const accountActivation = createAction(AccountActionsTypes.AccountActivation, props<{formula : string}>());
export const accountActivationSuccess = createAction(AccountActionsTypes.AccountActivationSuccess, props<{message : string}>());
export const accountActivationFailed = createAction(AccountActionsTypes.AccountActivationFailed, props<{error : string}>());
效果
login$ = createEffect(() =>
this.actions$.pipe(
tap( kek => {/*console.log(kek)*/}),
ofType(AccountActionsTypes.AccountLogin),
exhaustMap(({email: email, password: password}) => this.accountService.login(email,password)
.pipe(
map((response : { body: {account : AccountModel, token : string, message: string, status: string}}) =>
({type: AccountActionsTypes.AccountLoginSuccess, account: response.body.account, token: response.body.token, message: response.body.message, status: response.body.status })),
catchError(error => of({type: AccountActionsTypes.AccountLoginFailed, error: error })),
tap(response => {
/*console.log(response)*/;
}),
))
));
服务
private _options = { headers: new HttpHeaders({ 'Content-Type': 'application/json' }) };
login(email: string, password: string): Observable<Object> {
return this.http.post('http://localhost:8080/user/login', {email: email, password: password}, this._options); }
AccountLoginComponent
onLogin() {
this.store.dispatch(login({email : this.loginForm.value.email, password: sha1(this.loginForm.value.password)}));
this.loginResult$ = this.store.pipe(select(selectLoginStatus));
this.loginResultSub = this.loginResult$.subscribe(({loginStatus, message}) => {
this.isSubscribe = true;
this.message = message;
if(loginStatus === 'success') {
this.router.navigate(['/home']);
}
});
}
问题之所以出现,是因为如果登录错误,我会将令牌和帐户设置为不确定状态。我这样修复:
修复效果
login$ = createEffect(() =>
this.actions$.pipe(
ofType(AccountActionsTypes.AccountLogin),
exhaustMap(({email: email, password: password}) => this.accountService.login(email,password)
.pipe(
map((response : { body: {account : AccountModel, token : string, message: string, status: string}}) => {
if(response.body.token !== undefined) {
return {type: AccountActionsTypes.AccountLoginSuccess, account: response.body.account, token: response.body.token, message: response.body.message, status: response.body.status };
} else {
return {type: AccountActionsTypes.AccountLoginWrong, message: response.body.message, status: response.body.status };
}
}),
catchError(error => of({type: AccountActionsTypes.AccountLoginFailed, error: error })),
)
)
));
新动作
export const loginWrong = createAction(AccountActionsTypes.AccountLoginWrong, props< {message: string, status: string}>());
减速器
const _accountReducer = createReducer(
initialState,
on(AccountActions.loginSuccess, (state, { account, token, message, status } ) => ({
...state, account: account, token: token, message: message, loginStatus: status
})),
on(AccountActions.loginWrong, (state, { message, status } ) => ({
...state, message: message, loginStatus: status
})),
on(AccountActions.logout, (state) => ({
...state, account: null, message: "", token: ""
})),
on(AccountActions.accountActivationSuccess, (state, { message } ) => ({
...state, message: message
})),
);