angular - 效果 "AuthEffects.authLogin$"发送无效操作 : undefined

标签 angular redux rxjs observable side-effects

在 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 6rxjs 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/

相关文章:

Angular 2 - 显示一个元素并隐藏其他元素,

cordova - 如何向 ionic 推送通知添加操作按钮?

javascript - 如何使用 Normalizr 为递归模型定义模式

Angular HTTP拦截器如何链接一个可观察的

javascript - RxJS:每次返回并行 http 请求时更新客户端

angular - 小时显示 hourSegments Angular 日历

javascript - Angular 从父组件获取所有子组件的状态

javascript - 使用扩展运算符更新包含对象的数组

reactjs - Redux-saga上传文件进度事件

angular - RxJs Observable - 通过发出默认值处理 404