第二次动作调度在 RxJS 和 Angular 6 中不起作用
Action dispatch the second time doesn't effect in RxJS and Angular 6
我有一个管理登录的@Effect。步骤如下:
- 调用服务
- 保存令牌(进入class);
- Select 一个应用程序商店,看看用户是否询问了另一个页面(在重定向到登录之前。因为也许他想进入 'profile' 页面,但后来我将他重定向到登录, 保存想要的页面 'profile')。在这种情况下重定向用户
- 执行其他操作(设置变量'isAuthenticated'、保存令牌、解码令牌、在商店中)。
一切正常。这是auth.effects.ts的代码:
@Injectable()
export class AuthEffects {
constructor(private store: Store<fromApp.AppState>, private actions$: Actions, private router: Router, private authService: AuthService, private route: ActivatedRoute, private toastr: ToastrService) {
}
tokenObj: { token: string };
@Effect()
authLogin$ = this.actions$
.ofType(AuthActions.DO_LOGIN)
.pipe(map((action: AuthActions.DoLogin) => {
return action.payload;
})
, switchMap((authData: { email: string, password: string }) => {
return from(this.authService.login(authData.email, authData.password));
})
, map(tokenObj => this.tokenObj = tokenObj)
, withLatestFrom(this.store.select(('core')))
, take(1)
, map(([action, storeState]) => {
if (storeState.redirectUrl) {
this.router.navigate([storeState.redirectUrl]);
} else {
this.router.navigate(['/']);
}
})
, mergeMap(() => {
return [
{
type: AuthActions.LOGIN
},
{
type: AuthActions.SET_TOKEN,
payload: this.tokenObj.token
},
{
type: ProfileActions.DECODE_TOKEN,
payload: this.tokenObj.token
},
{
type: CoreActions.REMOVE_REDIRECT_URL
}
];
})
, catchError((err, caught) => {
this.toastr.error(err.message);
// Quindi, alla fine, torniamo l'Observable di errore, affinché si possa ri-provare l'operazione
return caught;
})
);
}
这是login.component.ts里面的函数:
onLogin(form: NgForm) {
const email = form.value.email;
const password = form.value.password;
this.store.dispatch(new AuthActions.DoLogin({ email: email, password: password }));
}
这是header.component.ts中触发注销的函数:
onLogout() {
this.store.dispatch(new AuthActions.Logout());
this.store.dispatch(new ProfileActions.CancelLoggedUser());
this.router.navigate(['/login']);
}
问题 是:如果我注销,我再次输入电子邮件和密码,然后按登录,但没有任何反应。特别是,打开 Ngrx DevTools,我看到 DO_LOGIN 已调度(具有表单的 属性 值)但未调用服务器。事件如果我在效果中放置一个断点,它不会触发。为什么?
这是所有操作的屏幕:登录--->主页--->注销--->第二次登录:
问题来自取消订阅可观察到的效果的take(1)
。
一个ngrx effect是一个单例,一旦退订就永远不会再订阅。
我有一个管理登录的@Effect。步骤如下:
- 调用服务
- 保存令牌(进入class);
- Select 一个应用程序商店,看看用户是否询问了另一个页面(在重定向到登录之前。因为也许他想进入 'profile' 页面,但后来我将他重定向到登录, 保存想要的页面 'profile')。在这种情况下重定向用户
- 执行其他操作(设置变量'isAuthenticated'、保存令牌、解码令牌、在商店中)。
一切正常。这是auth.effects.ts的代码:
@Injectable()
export class AuthEffects {
constructor(private store: Store<fromApp.AppState>, private actions$: Actions, private router: Router, private authService: AuthService, private route: ActivatedRoute, private toastr: ToastrService) {
}
tokenObj: { token: string };
@Effect()
authLogin$ = this.actions$
.ofType(AuthActions.DO_LOGIN)
.pipe(map((action: AuthActions.DoLogin) => {
return action.payload;
})
, switchMap((authData: { email: string, password: string }) => {
return from(this.authService.login(authData.email, authData.password));
})
, map(tokenObj => this.tokenObj = tokenObj)
, withLatestFrom(this.store.select(('core')))
, take(1)
, map(([action, storeState]) => {
if (storeState.redirectUrl) {
this.router.navigate([storeState.redirectUrl]);
} else {
this.router.navigate(['/']);
}
})
, mergeMap(() => {
return [
{
type: AuthActions.LOGIN
},
{
type: AuthActions.SET_TOKEN,
payload: this.tokenObj.token
},
{
type: ProfileActions.DECODE_TOKEN,
payload: this.tokenObj.token
},
{
type: CoreActions.REMOVE_REDIRECT_URL
}
];
})
, catchError((err, caught) => {
this.toastr.error(err.message);
// Quindi, alla fine, torniamo l'Observable di errore, affinché si possa ri-provare l'operazione
return caught;
})
);
}
这是login.component.ts里面的函数:
onLogin(form: NgForm) {
const email = form.value.email;
const password = form.value.password;
this.store.dispatch(new AuthActions.DoLogin({ email: email, password: password }));
}
这是header.component.ts中触发注销的函数:
onLogout() {
this.store.dispatch(new AuthActions.Logout());
this.store.dispatch(new ProfileActions.CancelLoggedUser());
this.router.navigate(['/login']);
}
问题 是:如果我注销,我再次输入电子邮件和密码,然后按登录,但没有任何反应。特别是,打开 Ngrx DevTools,我看到 DO_LOGIN 已调度(具有表单的 属性 值)但未调用服务器。事件如果我在效果中放置一个断点,它不会触发。为什么?
这是所有操作的屏幕:登录--->主页--->注销--->第二次登录:
问题来自取消订阅可观察到的效果的take(1)
。
一个ngrx effect是一个单例,一旦退订就永远不会再订阅。