为什么在canActivate()之前调用ngOnInit()?

时间:2018-06-07 18:22:23

标签: javascript angular typescript view canactivate

我正在使用路线保护,特别是canActivate()方法,但Angular在 ngOnInit()之前调用我的根AppComponent canActivate是调用。

我必须在canActivate之前等待AppComponent中的某些数据才能在模板中呈现它。

我该怎么做?

2 个答案:

答案 0 :(得分:1)

我正在处理这类案件,这就是我通常做的事情:

1。我创建了一个解析器服务(实现了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。以下是我们如何处理实施CanActivate界面的 AuthGuard

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. 然后你可以将解析器 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方法(它是通常的getter)从getResult存储结果,并返回此布尔结果(我们的AuthGuard期望返回布尔值,并且路由将如果它返回true则被激活,如果它返回false则不会被激活;

这是最简单的例子,没有任何额外的数据操作,逻辑通常更复杂,但这个骨架应该足以基本理解。

答案 1 :(得分:0)

对我来说,我在应用组件中监听了ROUTE_NAVIGATED事件,如下所示:

我正在使用ngrx/router-store来收听这些路由器操作。

  // app.component.ts
  public ngOnInit(): void {
    // grab the action stream
    this.actions$.pipe(
      // Only pay attention to completed router 
      ofType(ROUTER_NAVIGATED),
      // Now I can guarantee that my resolve has completed, as the router has finsihed
      // Switch 
      switchMap(() => {
        // Now switch to get the stuff I was waiting for 
        return this.someService.getStuff();
      })
    // Need to subscribe to actions as we are in the component, not in an effect
    // I suppose we should unsubscribe, but the app component will never destroy as far as I am aware so will always be listening
    ).subscribe();