Angular @ngrx/存储预加载保护捕捉错误

Angular @ngrx/存储预加载保护捕捉错误,angular,rxjs,ngrx,ngrx-effects,ngrx-store-4.0,Angular,Rxjs,Ngrx,Ngrx Effects,Ngrx Store 4.0,我正在使用@ngrx/store处理角度保护,以检查状态是否已加载,并且我面临一个问题,即如果我使用过滤器,canActivate方法将永远不会返回 下面是GetCompanies操作的示例效果: return this.companiesService.getCompanies() .pipe( map(companies => new companiesActions.GetCompaniesSuccess(companies)), catchError(error

我正在使用@ngrx/store处理角度保护,以检查状态是否已加载,并且我面临一个问题,即如果我使用过滤器,
canActivate
方法将永远不会返回

下面是GetCompanies操作的示例效果:

return this.companiesService.getCompanies()
  .pipe(
    map(companies => new companiesActions.GetCompaniesSuccess(companies)),
    catchError(error => Observable.of(new companiesActions.GetCompaniesFail(error)))
  )
如果出现错误,我将调度GetCompanysFail操作并将用户重定向到
/login
页面。很好,有趣的是警卫

@Injectable()
export class CompaniesGuard implements CanActivate {
  constructor(
    private store: Store<AppState>,
    private router: Router
  ) {}

  canActivate(): Observable<boolean> {
    return this.checkStore()
      .pipe(
        switchMap(() => Observable.of(true)),
        catchError(() => Observable.of(false))
      );
  }

  checkStore(): Observable<boolean> {
    return this.store.select(getCompaniesLoaded)
      .pipe(
        tap(loaded => {
          if (!loaded) {
            this.store.dispatch(new companiesActions.GetCompanies());
          }
        }),
        filter(loaded => loaded),
        take(1)
      );
  }
}
@Injectable()
导出类公司Guard实现CanActivate{
建造师(
私家店,
专用路由器
) {}
canActivate():可观察的{
返回这个。checkStore()
.烟斗(
开关映射(()=>可观察的(真)),
捕捉错误(()=>可观察到的(错误))
);
}
checkStore():可观察{
返回此.store.select(GetCompanyLoaded)
.烟斗(
点击(已加载=>{
如果(!已加载){
this.store.dispatch(new companyActions.getcompanys());
}
}),
过滤器(已加载=>已加载),
采取(1)
);
}
}
如果出现错误且loaded不为false,
canActivate
将不会返回任何内容,因为
checkStore
不执行任何操作

如果我将
filter
更改为
map
,它会工作,但只接受第一个值,即
false
,即使数据将成功加载

我错过了什么?我如何处理那里的HTTP错误?有没有一种方法可以等待特定的状态,或者在
checkStore
中抛出错误


提前感谢

如果你把责任分开一点,这似乎更容易处理

不管怎样,您都应该运行
checkStore
,而不是直接依赖它的结果。相反,让商店告诉你成功或失败,并返回结果

请注意,ngrx和redux鼓励单向数据流,以简化应用程序逻辑

中的存储属性
getCompaniesLoadedStatus
初始化为initial,并在
companiesActions.GetCompaniesSuccess
companiesActions.GetCompaniesFail
中设置为success或failed

重试是在服务中处理的(靠近提取)

canActivate():可观察{
这是checkStore();
返回此.store.select(GetCompanyLoadedStatus).pipe(
过滤器(状态=>status!=='initial'),
映射(状态=>状态=='success'?真:假)
);
}
checkStore():void{
this.store.select(GetCompanyLoadedStatus).pipe(
取(1)//这样就不需要取消订阅
).订阅(状态=>
如果(状态=='initial'){
this.store.dispatch(new companyActions.getcompanys());
}
);
}

我不确定您是否应该在guards中进行http调用。这意味着在每次页面更改时,您都会发出http请求。这不仅是无用的请求,而且如果用户为其互联网付费,您将让他为不必要的请求付费。你确定要这么做吗?你的警卫到底在测试什么情况?@trichetriche我认为他的计划是打电话,把数据放在缓存(ngrx)中,然后从那时起引用它。问题是它在第一页加载时不在缓存中。至少这是我的问题。我也遇到过同样的情况,我通过设置我的效果以在出错时重试来解决它。您对错误的期望结果是什么?您希望
canActivate
发出false吗?这很有趣,我可以有三个值而不是两个值,这样更容易。使用这种方法,可以使用
过滤器直接从checkStore返回Observable(状态=>status!==“initial”
,然后在canActivate check
中返回this.checkStore().pipe(开关映射(状态=>status==“success”?true:false))
听起来你可能没有抓住要点,那就是
canActivate
应该与
checkStore
分离。事实上,我这样做的方式是在服务中进行检查。