Эффект AuthEffects.authLogin $ отправил недопустимое действие: undefined

В приложении Angular 6 (и RxJS) у меня есть эффект, который управляет логином. Сначала он вызывает сервер, а затем устанавливает и декодирует токен. В конце я добавил последнюю операцию, которая обрабатывает перенаправление.

Это так: пользователь (не авторизованный) пытается получить доступ на странице профиля. В 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.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();
            }));
}),

Итак, я смотрю на это поведение: после того, как пользователь вошел в систему, я сохраняю токен, я (в конечном итоге) перенаправляю на нужную страницу, а затем удаляю эту страницу из состояния. Я уверен, что первая mergeMap () работает .. все было сломано, когда я добавил последний кусок (выхлопная карта), и я не могу найти решение для ошибки консоли:

ОШИБКА Ошибка: эффект «AuthEffects.authLogin $» отправил недопустимое действие: undefined

Если я изменю положение последнего «возврата»:

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
        }));

У меня ошибка компиляции на excMap ():

Аргумент типа '() => void' не может быть назначен параметру типа '(значение: {type: string; payload ?: undefined;} | {type: string; payload: any;}, index: number) .. . '. Тип 'void' не может быть назначен типу 'ObservableInput ‹{}>'


person panagulis72    schedule 04.07.2018    source источник


Ответы (1)


Используя 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}). Однако это также давало мне ошибку, аналогичную ошибкам, которые вы описываете выше. Я решил, что функция map() внутри pipe() не требует побочных эффектов. Я решил свою проблему, просто используя 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)))
      )
    )
  );
person tlm    schedule 05.10.2018
comment
Как ни странно, карта позволяет создавать побочные эффекты, но не любит, когда вы это делаете. - person hima; 15.10.2020