Как сделать http пост-вызов внутри маршрутной охраны в angular7? - PullRequest
0 голосов
/ 25 февраля 2020

У меня есть приложение Angular 7, в котором у меня есть пост-звонок, и на основании этого пост-звонка я хочу сделать охрану активным / неактивным. У меня есть мой охранник маршрута, подобный этому

canActivate = (_router: ActivatedRouteSnapshot): boolean => {
    console.log('in link expiry guard')
    let userEmail = _router.paramMap.get('email');
    let isAllow;

    console.log('params : ', userEmail)
    userEmail = this._utilityService.decryptMsgByCryptoJs(userEmail);
    console.log('user email : ', userEmail)
    this._dataService.post(this._const.userResetPasswordLinkExpiry, { email: userEmail }).subscribe(resp => {
        console.log('verify response : ',resp)
        if (resp.success) {
            console.log('in success')
            isAllow = true;
        } else {
            isAllow = false;
        }
    })
    console.log('allow flag  : ',isAllow)
    if (isAllow) {
        console.log('in allow')
        return true;
    } else {
        console.log('in not allow')
        this._utilityService.navigate('/login');
        this._dataService.exhangeResetPasswordObsMsg({ event: 'linkExpired' });
        return false;
    }
}

Но проблема в том, что пока мой вызов http post выполняется, поэтому мой охранник выполняется полностью и возвращает ложное значение, и после того, как этот ответ поступил от почтового вызова , Как я могу управлять этим сценарием, чтобы сделать маршрут истинным или ложным на основе ответа на вызов http post.

1 Ответ

0 голосов
/ 25 февраля 2020

Если вы хотите сделать запрос Http внутри вашей функции canActivate, вам нужно вернуть Observable<boolean> вместо boolean, поскольку вы сейчас выполняете асинхронное действие.

И так как если вы хотите перейти в случае сбоя, вы должны вернуть Observable<boolean | UrlTree>.

Простая версия

constructor(private router: Router) { }

canActivate(route: ActivatedRouteSnapshot, 
    state: RouterStateSnapshot): Observable<boolean | UrlTree> {
  return this.http.post(url, body).pipe(
    map((resp: any) => resp.success ? true : this.router.parseUrl('/path'))
  );   
}

Мы возвращаем наблюдаемый http-запрос (маршрутизатор вызовет его, подписавшись), и сопоставив ответ либо с

  • true - маршрутизатор может перейти к защищенному маршруту
  • UrlTree - маршрутизатор должен перейти к маршруту, который мы возвратили

Применительно к вашему примеру

Если мы применим это к вашему примеру, нам нужно проделать немного больше работы в конвейере, так как у вас есть дополнительный сервисный вызов.

// TODO: inject other services
constructor(private router: Router) { }

canActivate(route: ActivatedRouteSnapshot, 
      state: RouterStateSnapshot): Observable<boolean | UrlTree> {
    const userEmail = route.paramMap.get('email');

    // I am assuming this is a synchronous call
    userEmail = this._utilityService.decryptMsgByCryptoJs(userEmail);

    const url = this._const.userResetPasswordLinkExpiry;
    const body = { email: userEmail };

    return this._dataService.post(url, body).pipe(
      // initial map from response to true/false
      map((resp: any) => resp.success),

      // perform an action if false
      tap(success => {
        if (!success) {
          // I'm assuming this is synchronous. If not, you will need to do a switchMap
          this._dataService.exhangeResetPasswordObsMsg({ event: 'linkExpired' });
        }
      }),
      // final map to boolean | UrlTree
      map(success => success ? true : this.router.parseUrl('/login'))
    );   
}

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

...