Ionic 4 - Задержка разрешения на маршрутизацию страницы AuthGuard - PullRequest
2 голосов
/ 03 октября 2019

У меня есть приложение ionic 4, которое изначально хранит информацию о пользователе. Когда пользователь открывает приложение, то, если его информация там, я хочу, чтобы он был отправлен на домашнюю страницу. Если это не так, я хочу, чтобы он был перенаправлен на страницу входа, вполне нормально.

Проблема, с которой я сталкиваюсь, заключается в том, что примерно через 500 мс вы увидите страницу входа, а затем, прочитав информацию , затем перенаправит вас на домашнюю страницу.

Я хотел бы, чтобы приложение ПОДОЖДИТ В ответе из хранилища до оно направляет вас на страницу входа или домашнюю страницу.

App.component.ts

  public initializeApp(): void {
    this.platform.ready().then((): void => {
      this.statusBar.styleDefault();
      this.splashScreen.hide();
      this.authService.authState.subscribe((state: boolean): void => {
        if (state) {
          this.router.navigate(['home']);
        } else {
          this.router.navigate(['login-register']);
        }
      });
      this.permissionService.requestCameraPermission();
    });
  }

AuthService.service.ts

public readonly authState: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false)

  private _ifLoggedIn(): void {
    // just sees if his info is saved, if so then he has been logged in
    this.userService.getUserInfo().then((response: UserData): void => {
      if (response) {
        this.authState.next(true);
      }
    });
  }

  public isAuthenticated(): boolean {
    return this.authState.value;
  }

AuthGuard

export class AuthGuardService {
  private authService: AuthService;

  public constructor(authService: AuthService) {
    this.authService = authService;
  }
  public canActivate(): boolean {
    return this.authService.isAuthenticated();
  }
}

app-routing.module.ts

const routes: Routes = [
  {
    path: '',
    redirectTo: 'login-register',
    pathMatch: 'full',
  },
  {
    path: 'login-register',
    loadChildren: () => import('../pages/login-register/login-register.module').then(m => m.LoginRegisterPageModule),
  },
  {
    path: 'home',
    loadChildren: () => import('../pages/home/home.module').then(m => m.HomePageModule),
    canActivate: [AuthGuardService],
  },
];

если есть что-то еще, что вам нужно, дайте мне знать. Спасибо, ребята!

1 Ответ

2 голосов
/ 03 октября 2019

Первая проблема, с которой вы столкнулись, это BehaviorSubject, которая была инициализирована, поэтому она будет возвращать результат напрямую, когда вы запрашиваете результат.

Вторая проблема состоит в том, что isAuthenticated() возвращает значение, потому что онометод синхронизации, но вам нужен любой, кто вызывает его, чтобы ждать.

Решение состоит в том, чтобы использовать ReplySubject и сделать isAuthenticated() async.

AuthService.service.ts

public readonly authState: ReplaySubject<boolean> = new ReplaySubject<boolean>(1)

  private _ifLoggedIn(): void {
    // just sees if his info is saved, if so then he has been logged in
    this.userService.getUserInfo().then((response: UserData): void => {
        this.authState.next(!!response);
    }, (reason) => this.authState.next(false));
  }

  public async isAuthenticated(): Promise<boolean> {
    return this.authState.asObservable().pipe(take(1)).toPromise();
  }

Обратите внимание, что this.authState.next(false) должен возвращать результат, а не зависать вечно, поэтому, если ошибка возвращается как ошибка 401, он будет считать, что она не вошла в систему.

И this.authState.next(!!response) - это просто сокращенный формат для вашего предыдущего условия, и он будет обрабатывать случай, если ответ возвращается с null или undefined, если вы реализовали .getUserInfo() таким образом, что пользователь не вошел в систему.

AuthGuard

export class AuthGuardService implements CanActivate {
  private authService: AuthService;

  public constructor(authService: AuthService) {
    this.authService = authService;
  }
  public async canActivate(): Promise<boolean> {
    return this.authService.isAuthenticated();
  }
}

Обратите внимание, что canActivate() уже поддерживает асинхронную реализацию, также я добавил implements CanActivate, так что это имеет больше смысла.

Вы можете узнать больше отипы Subject здесь: Понимание поведения rxjsorSubject, ReplaySubject и AsyncSubject

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...