Почему ngOnInit () вызывается до canActivate ()? - PullRequest
0 голосов
/ 07 июня 2018

Я использую средства защиты маршрута, в частности, метод canActivate(), но Angular вызывает ngOnInit() моего корня AppComponent до вызова canActivate.

Iпридется ждать некоторых данных в canActivate, прежде чем AppComponent сможет их отобразить в шаблоне.

Как я могу это сделать?

1 Ответ

0 голосов
/ 07 июня 2018

Я имел дело с такими случаями, и вот что я обычно делаю:

1. Я создаю службу Resolver (которая реализует Resolve интерфейс).Это позволяет вам получить все необходимые данные до активации маршрута:

import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router';
import { DataService } from 'path/to/data.service';

@Injectable()
export class ExampleResolverService implements Resolve<any> {
  constructor(private _dataService: DataService) { }

  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<any> {
    return this._dataService.anyAsyncCall()
      .then(response => {
        /* Let's imagine, that this method returns response with field "result", which can be equal to "true" or "false" */
        /* "setResult" just stores passed argument to "DataService" class property */
        this._dataService.setResult(response.result);
      })
      .catch(err => this._dataService.setResult(false););
  }
}

2. Вот как мы можем иметь дело с AuthGuard , который реализует CanActivate интерфейс:

import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
import { DataService } from 'path/to/data.service';

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(private _dataService: DataService) { }

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    /* "getResult" method operates with the same class property as setResult, it just returns the value of it */
    return this._dataService.getResult(); // will return "true" or "false"
  }
}

3. Затем вы можете включить Resolver и AuthGuard к вашей конфигурации маршрутов, здесь только часть (структура маршрутов может отличаться, вот пример с активацией родительского компонента):

const routes: Routes = [
  {
    path: 'app',
    component: AppComponent,
    resolve: {
      result: ExampleResolverService // your resolver
    },
    canActivate: [AuthGuard], // your AuthGuard with "canActivate" method
    children: [...] // child routes goes inside the array
  }
];

Как это работает

Когда вы переходите к /app, ExampleResolverService запускается, выполняет API-вызов и сохраняет необходимую часть ответа на свойство класса в DataService с помощью метода setResult (это обычный установщик).Затем, когда распознаватель закончил работу, пришло время для нашего AuthGuard.Он получает сохраненный результат из DataService с помощью метода getResult (это обычный метод получения) и возвращает этот логический результат (наш AuthGuard ожидает, что логическое значение будет возвращено, и маршрут будет активирован, если он вернет true, ине будет активирован, если вернет false);

Это самый простой пример без каких-либо дополнительных операций с данными, обычно логика более сложная, но этого каркаса должно быть достаточно для базового понимания.

...