守卫没有等待api响应

时间:2018-11-14 15:43:15

标签: angular ngrx angular7

我正在使用angular 7和ngrx,当我去商店中没有数据的路线时,我会调用API来收费。

我遵循了ngrx的example-app,并使用了 guards 。我的问题是,当我直接访问路线http://localhost:4200/#/anomalies/view/28时,guard启动了,但是当它调用API时,将网址更改为http://localhost:4200/,然后逐步转到默认路由。如果我使用RouteLink访问该URL,只有重新加载(按F5键)或在浏览器中键入时,才没有任何问题。

有一种方法可以迫使路由器等待直到警卫结束?

谢谢

Route.ts

export const routes: Routes = [
  {
    path: 'list',
    component: ListPageComponent,
    canActivate: [AnomalyTypesExistsGuard],
    children: [
      {
        path: 'tab',
        component: TableSubPageComponent,
        outlet: 'viewer',
      },
      {
        path: 'map',
        component: MapSubPageComponent,
        outlet: 'viewer',
        data: { 'map': true }
      },
    ]
  },
  {
    path: 'view/:id',
    component: AnomalyComponent,
    canActivate: [AnomalyExistsGuard]
  },
  {
    path: '',
    redirectTo: '/anomalies/list/(viewer:tab)'
  }
];

anomaly-exist.guard.ts

@Injectable({
  providedIn: 'root'
})
export class AnomalyExistsGuard implements CanActivate {
  constructor(
    private store: Store<fromAnomalies.State>,
    private anomaliesService: AnomaliesService,
    private router: Router
  ) {}

  waitForCollectionToLoad(): Observable<boolean> {
    return this.store.pipe(
      select(fromAnomalies.getAnomaliesLoaded),
      filter(loaded => loaded),
      take(1)
    );
  }

  hasAnomalyInStore(id: number): Observable<boolean> {
    return this.store.pipe(
      select(fromAnomalies.getAnomalyEntities),
      map(entities => !!entities[id]),
      take(1)
    );
  }

  hasAnomalyInApi(id: number): Observable<boolean> {
    return this.anomaliesService.getAnomalyByID(id).pipe(
      map(anomalyEntity => new AnomalyActions.LoadAnomaly(anomalyEntity)),
      tap((action: AnomalyActions.LoadAnomaly) => this.store.dispatch(action)),
      map(anomaly => !!anomaly),
      catchError(() => {
        this.router.navigate(['/404']);
        return of(false);
      })
    );
  }

  hasAnomaly(id: number) {
    return this.hasAnomalyInStore(id).pipe(
      switchMap(inStore => {
        if (inStore) {
          return of(inStore);
        }

        return this.hasAnomalyInApi(id);
      })
    );
  }

  canActivate(route: ActivatedRouteSnapshot): Observable<boolean> {
    return this.waitForCollectionToLoad().pipe(
      switchMap(() => this.hasAnomaly(route.params['id']))
    );
  }
}

0 个答案:

没有答案