NgRx Call диспетчерское действие в Angular Router Guard будет выполнять бесконечный цикл - PullRequest
1 голос
/ 10 июля 2019

История:

Привет всем.Я новичок в использовании библиотеки NgRx.В моем угловом проекте я использую защиту от маршрутизатора для предотвращения неаутентифицированного пользователя на неаутентифицированном веб-сайте.

Мой идеал - вызвать api rest rest для проверки содержимого токена локального хранилища.Если результат остальных API равен "success", за до возврата (true) выполните "store.dispatch (LoginSuccess)" , чтобы обновить информацию об авторизации входа в Store.

Проблема:

Когда выполняются действия по отправке.Действие «LoginSuccess» всегда выполняет бесконечный цикл, даже устанавливая {dispatch: false} в @ Effect () .После попробуйте и поиск по Google решение для этого.Эта проблема всегда в моем проекте.Надеюсь, что некоторые друзья по stackoverflow могут помочь мне. ~ Спасибо.

часть кодов:

auth.guard.ts

.....
....
canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {

    const authData: {email: string, token: string} = JSON.parse(
          String(localStorage.getItem('User')));

    const authToken = authData && authData.token;

    // loginServ is a REST API for verify token
    return this.loginServ.VerifyToken(authToken).pipe(
      concatMap((res: AuthResult) => {
        if (res.result === 'success') {

          this.store.dispatch(LoginSuccess({
            isAuthenticated: true,
            email: authData && authData.email,
            token: authToken,
            result: 'success',
            message: 'success'
          }));  // <-- execute action infinite.

          return of(true);
        } else {

          this.store.dispatch(LoginFailed({
            isAuthenticated: false,
            email: authData && authData.email,
            token: authToken,
            result: 'failed',
            message: 'token illegal'
          }));

          localStorage.removeItem('User');
          this.router.navigate(['']);
          return of(false);
        }
      })
    );
...
...

action.ts:

...
export const LoginSuccess = createAction(
  '[auth] Login Success',
  props<{
    isAuthenticated: boolean,
    email: string,
    token: string,
    result: string,
    message: string,
  }>()
);
....
...

reducer.ts

....
....
export const loginReducer = createReducer(
  defaultState,

  on(Login),

  on(LoginSuccess, (state, userInfo) => {
    console.log(state);     // <-- for debug.
    console.log(userInfo);  // <-- for debug.
    return {
      ...state,
      ...userInfo
    };
  }),

  on(LoginFailed, (state, result) => {
    return {
      ...state,
      ...result
    };
  }),
....
...

effect.ts

....
...
loginSuccess = createEffect(() => this.actions$
  .pipe(
    ofType(LoginSuccess),
    map((user: any) => {

      console.log(user);
      const beStoreInfo = {
        email: user.email,
        token: user.token,
      };

      localStorage.setItem(
        'User',
        JSON.stringify(beStoreInfo));
        return {
          type: '[auth] Login Success',
          isAuthenticated: true,
          email: user.email,
          token: user.token,
          result: user.result,
          message: user.message
        };
    }),
  ), {dispatch: false});
....
...

service_overview-routing.module.ts

....
// using lazy loading module
const routes: Routes = [
  {
    path: '',
    canActivate: [AuthGuard],
    component: ServiceOverviewComponent},
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class ServiceOverviewRoutingModule { }
....

app-routing.module.ts

Использование ленивого загрузочного модуля.

....
...
const routes: Routes = [
  { path: 'login', loadChildren: () => import('./login/login.module')
    .then(m => m.LoginModule)},
  { path: 'register', loadChildren: () => import('./register/register.module')
    .then(m => m.RegisterModule)},
  { path: 'service_overview', loadChildren: () => import('./service-overview/service-overview.module')
    .then(m => m.ServiceOverviewModule)},
  { path: '', redirectTo: 'login', pathMatch: 'full' }
];
....

Среда:

УгловаяCli: 8.0.3

NgRx Store / Effect: 8.0.1

ОС: Ubuntu 18.04

.. Спасибо

...