在 Angular 6(和 RxJS)应用程序中,我有一个 Effect 来管理登录。它首先调用服务器,然后设置和解码 token 。最后我添加了一个处理重定向的最后一个操作。
是这样的: 用户(未登录)尝试访问个人资料页面。在 AuthGuard 中,我拦截它并保存所需的页面 (auth-guard.service.ts):
.. Here I already know that the user is not authenticated.
let url = state.url;
if (url) {
.. I save in the Store the url
this.store.dispatch(new CoreActions.SaveRedirectUrl(url));
}
this.router.navigate(['/login']);
return false;
这是 Auth Effect 的最后两部分(auth.effects.ts,在我发送操作 DO_LOGIN 时调用):
, mergeMap((tokenObj: any) => {
return [
{
type: AuthActions.LOGIN
},
{
type: AuthActions.SET_TOKEN,
payload: tokenObj.token
},
{
type: ProfileActions.DECODE_TOKEN,
payload: tokenObj.token
}
];
})
, exhaustMap(() => {
return this.store.select('core')
.pipe(
map(coreState => {
if (coreState.redirectUrl) {
this.router.navigate([coreState.redirectUrl]);
} else {
this.router.navigate(['/']);
}
new CoreActions.RemoveRedirectUrl();
}));
}),
所以我正在查看此行为:在用户登录后,我保存 token ,我(最终)重定向到所需的页面,然后我从状态中删除该页面。我确定第一个 mergeMap() 有效.. 当我添加最后一 block (exhaustMap) 时一切都坏了,我找不到控制台错误的解决方案:
ERROR Error: Effect "AuthEffects.authLogin$" dispatched an invalid action: undefined
如果我改变最后一个“return”的位置:
this.store.select('core') -----> from here
.pipe(
map(coreState => {
if (coreState.redirectUrl) {
this.router.navigate([coreState.redirectUrl]);
} else {
this.router.navigate(['/']);
}
return new CoreActions.RemoveRedirectUrl(); -----> to here
}));
我在 exhaustMap() 上有一个编译错误:
Argument of type '() => void' is not assignable to parameter of type '(value: { type: string; payload?: undefined; } | { type: string; payload: any; }, index: number) ...'. Type 'void' is not assignable to type 'ObservableInput<{}>'
最佳答案
使用 Angular 6 和 rxjs 6.0.0
:
我最近在管理我的 ngrx
登录时遇到了类似的问题,并遵循了与您在上面描述的类似的模式。在我的 $login
效果中,我最初有:
@Effect()
login$ = this.actions$.pipe(
ofType<Login>(AuthActionTypes.Login),
map(action => action.payload),
exhaustMap((auth: Authenticate) =>
this.authService.loginWithUsernameAndPassword(auth).pipe(
map(user => {
if (user && user.token) {
this.cookieService.set('token', user.token)
}
new LoginSuccess({user})
return user;
}),
catchError(error => of(new LoginFailure(error)))
)
)
);
我正在返回 user
,这给了我一个错误,所以我放弃了它并尝试创建 new LoginSuccess({user})
。不过,这也给了我一个类似于您在上面描述的错误的错误。我认为 pipe()
中的 map()
函数不需要副作用。我最终通过使用 tap()
解决了我的问题创造我使用 cookieService
的“副作用”,因为 tap()
返回进入其中的相同对象。完成此操作后,一切都按预期运行——没有错误或异常。
@Effect()
login$ = this.actions$.pipe(
ofType<Login>(AuthActionTypes.Login),
map(action => action.payload),
exhaustMap((auth: Authenticate) =>
this.authService.loginWithUsernameAndPassword(auth).pipe(
// user tap to set my cookie and achieve my side effect
tap(user => {
if (user && user.token) {
this.cookieService.set('token', user.token)
}
}),
// use map without any side effect
map(user => new LoginSuccess({ user })),
catchError(error => of(new LoginFailure(error)))
)
)
);
关于angular - 效果 "AuthEffects.authLogin$"发送无效操作 : undefined,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51176645/