Неперехваченный (в обещании): ошибка типа: не удается прочитать свойство ‘includes’ неопределенного

#angular

#angular

Вопрос:

Я получил неожиданную ошибку при реализации auth.guard в моем проекте Angular. Я получаю его при нажатии на ссылку, которая защищена auth.guard.

auth.guard.ts

 import { Injectable } from "@angular/core";
import {
  CanActivate,
  Router,
  ActivatedRouteSnapshot,
  RouterStateSnapshot
} from "@angular/router";
import { AuthService } from "./auth.service";

@Injectable()
export class AuthGuard implements CanActivate {
  private url: string;
  constructor(private auth: AuthService, private router: Router) {}

  private handleAuthState(): boolean {
    if (this.isLoginOrRegister()) {
      this.router.navigate(["/rentals"]);
      return false;
    }
    return true;
  }
  private handleNotAuthState(): boolean {
    if (this.isLoginOrRegister()) {
      return true;
    }
    this.router.navigate(["/login"]);
    return false;
  }
  private isLoginOrRegister(): boolean {
    if (this.url.includes("login") || this.url.includes("register")) {
      return true;
    }
    return false;
  }

  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): boolean {
    let url: string = state.url;

    if (this.auth.isAuthenticated()) {
      return this.handleAuthState();
    }
    return this.handleNotAuthState();
  }
}
  

ошибка в консоли

 ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'includes' of undefined
TypeError: Cannot read property 'includes' of undefined
    at AuthGuard.push../src/app/auth/shared/auth.guard.ts.AuthGuard.isLoginOrRegister (auth.guard.ts:30)
    at AuthGuard.push../src/app/auth/shared/auth.guard.ts.AuthGuard.handleAuthState (auth.guard.ts:16)
    at AuthGuard.push../src/app/auth/shared/auth.guard.ts.AuthGuard.canActivate (auth.guard.ts:43)
    at router.js:3103
    at Observable._subscribe (defer.js:9)
    at Observable.push../node_modules/rxjs/_esm5/internal/Observable.js.Observable._trySubscribe (Observable.js:43)
    at Observable.push../node_modules/rxjs/_esm5/internal/Observable.js.Observable.subscribe (Observable.js:29)
    at TakeOperator.push../node_modules/rxjs/_esm5/internal/operators/take.js.TakeOperator.call (take.js:24)
    at Observable.push../node_modules/rxjs/_esm5/internal/Observable.js.Observable.subscribe (Observable.js:24)
    at subscribeTo.js:21
    at resolvePromise (zone.js:831)
    at resolvePromise (zone.js:788)
    at zone.js:892
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:423)
    at Object.onInvokeTask (core.js:17290)
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:422)
    at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:195)
    at drainMicroTaskQueue (zone.js:601)
    at ZoneTask.push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask [as invoke] (zone.js:502)
    at invokeTask (zone.js:1744)
defaultErrorLogger @ core.js:15724
push../node_modules/@angular/core/fesm5/core.js.ErrorHandler.handleError @ core.js:15772
next @ core.js:17771
schedulerFn @ core.js:13515
push../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.__tryOrUnsub @ Subscriber.js:196
push../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.next @ Subscriber.js:134
push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber._next @ Subscriber.js:77
push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next @ Subscriber.js:54
push../node_modules/rxjs/_esm5/internal/Subject.js.Subject.next @ Subject.js:47
push../node_modules/@angular/core/fesm5/core.js.EventEmitter.emit @ core.js:13499
(anonymous) @ core.js:17321
push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke @ zone.js:391
push../node_modules/zone.js/dist/zone.js.Zone.run @ zone.js:150
push../node_modules/@angular/core/fesm5/core.js.NgZone.runOutsideAngular @ core.js:17258
onHandleError @ core.js:17321
push../node_modules/zone.js/dist/zone.js.ZoneDelegate.handleError @ zone.js:395
push../node_modules/zone.js/dist/zone.js.Zone.runGuarded @ zone.js:164
_loop_1 @ zone.js:694
api.microtaskDrainDone @ zone.js:703
drainMicroTaskQueue @ zone.js:608
push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask @ zone.js:502
invokeTask @ zone.js:1744
globalZoneAwareCallback @ zone.js:1770
  

ошибка в консоли

Ответ №1:

Ну, .includes появляются ровно в двух местах в вашем скрипте, оба раза как this.url.includes . После объявления свойства url с ним больше ничего (в частности: присваивание) не происходит.

(И, кстати, вместо if (someBooleanExpression) return true; else return false; этого вы можете просто return someBooleanExpression .)

Ответ №2:

Внимательно посмотрите на AuthGuard.isLoginOrRegister (auth.guard.ts:30) часть.

Вы должны обработать обработчик исключений, такой как показано ниже. Обратитесь к следующим // HERE комментариям:

 private isLoginOrRegister(): boolean {
  // HERE
  if (this.url amp;amp; (this.url.includes("login") || this.url.includes("register"))) {
    return true;
  }
  return false;
}
...

canActivate(
  route: ActivatedRouteSnapshot,
  state: RouterStateSnapshot
): boolean {
  // HERE
  this.url = state.url;

  if (this.auth.isAuthenticated()) {
    return this.handleAuthState();
  }
  return this.handleNotAuthState();
}
  

Надеюсь, это вам поможет.

Ответ №3:

Публикую, просто чтобы объяснить, что произошло.

У вас есть эта строка

 let url: string = state.url; 
  

которое объявляет url переменной, ограниченной областью действия метода, в то время как свойство класса, объявленное выше, остается не инициализированным:

   private url: string;
  

Поэтому переходим на

 this.url = state.url; 
  

должно решить это, поскольку сообщение об ошибке находится в этой строке

 this.url.includes("login") || this.url.includes("register"))
  

и в нем говорится, что свойство равно нулю, что является истиной, вы его еще не инициализировали

Комментарии:

1. Помогло ли это вам, как вы говорили ранее?