【问题标题】:Angular + ngrx: Async canActive Guard must be cancelled from somewhere elseAngular + ngrx:必须从其他地方取消异步 canActive Guard
【发布时间】:2018-03-17 19:19:19
【问题描述】:

正如标题所说:有没有办法告诉路由器取消当前的导航?

情况如下:

  • 路由守卫调度一个动作。
  • 效果基于该操作执行异步调用。
  • 完成后,异步调用将对属性调度存储更新操作。
  • 守卫订阅了该属性的选择器(例如“property$”)
  • 一旦该属性$ 更新,守卫将决定是否允许导航。

此方法仅在效果的异步操作请求的资源正确返回时有效(HTTP 200)。但万一操作失败(比如 HTTP 404),问题就出在这里:

  • 守卫不会批准也不会拒绝导航。它处于待处理状态,并且在守卫返回 true 或 false 之前不会发生其他导航请求。

有没有办法实现调用,比如天真的说:this._router.cancelAllNavigationRequests()

【问题讨论】:

  • 嘿,当你的 HTTP 调用的响应不是 200 时,你不能改变你的警戒以重定向到默认的“错误页面”吗?
  • 您可以指示状态失败或让守卫监听效果将发出的动作。

标签: angular ngrx angular-router ngrx-effects angular-guards


【解决方案1】:

您没有提供任何代码,因为您的案例应该可以在不需要 cancelAllNavigationRequests 的情况下工作,您只是没有正确处理 HTTP 错误。这是我在警卫中使用的一种方法,它可能会帮助您或给您一些想法,它类似于 ngex 示例中的方法: 在调用服务之前,此 Guard 将检查 Classified 是否已经存在且不是部分的。

@Injectable()
export class ClassifiedGuardService implements CanActivate, CanActivateChild {
  constructor(private store: Store<fromRoot.State>, private classifiedService: ClassifiedService, private router: Router) {
  }

  vendorClassifiedAlreadyLoaded(id: string): Observable<boolean> {
    return this.store.pipe(
      select(fromContext.selectAllClassifieds),
      map(entities => {
        for (let i = 0; i < entities.length; i++) {
          if (entities[i].id === id && !entities[i].partial) {
            return true;
          }
        }
        return false;
      }),
      take(1)
    );
  }
  getVendorClassifiedFromServer(id: string) {
    return this.classifiedService.getVendorsClassified({id: id}).pipe(
      map(payload => new ClassifiedAction.GetVendorsClassifiedSuccess(payload)),
      tap((action: ClassifiedAction.GetVendorsClassifiedSuccess) => this.store.dispatch(action)),
      map(payload => !!payload),
      catchError(err => {
        this.store.dispatch(new ClassifiedAction.GetVendorsClassifiedFail(err));
        this.router.navigate(['/errors/bad-request']);
        return of(false);
      })
    );
  }


  getFullClassified(id: string): Observable<boolean> {
     return this.vendorClassifiedAlreadyLoaded(id).pipe(
        switchMap(inStore => {
          if (inStore) {
            return of(inStore);
          }
          return this.getVendorClassifiedFromServer(id);
        })
      );
  }

  canActivate(route: ActivatedRouteSnapshot): Observable<boolean> {
    return this.getFullClassified(route.params['id']);
  }

  canActivateChild(route: ActivatedRouteSnapshot) {
    return this.canActivate(route);
  }
}

【讨论】:

  • 您好,感谢您的评论,但您的代码不是基于 redux 的。这里的复杂性在于,守卫无法访问也无法看到 sotre 的效果和由此产生的动作调度。
猜你喜欢
  • 2019-01-19
  • 2021-02-04
  • 1970-01-01
  • 2023-04-06
  • 2023-01-20
  • 1970-01-01
  • 2013-06-11
  • 2018-05-15
  • 2021-05-29
相关资源
最近更新 更多