我在Angular中做了一个路由守卫,在允许访问所述路由之前,它会检查firestore中的某个值。
一旦HTTP云函数完成,该组件就被路由到。这个云函数在一个名为agreement
的firestore文档中创建一个对象,然后路由侦听该对象中的状态,以决定是否允许访问。然而,我们遇到的问题是,可能有9/10次,防护人员似乎认为agreement
对象不存在于文档中,因此抛出错误。(虽然我可以在firestore中看到协议对象!)。
我已经记录流,它正确地记录了订阅中的日志,然后是guard中的日志,因此在尝试路由和调用guard类之前,我知道HTTP函数正在完成。
这是守卫:
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
this.tenancyOffer$ = this._tenancyOffer.getTenancyOfferById(route.params.offerId).get({source: 'server'})).valueChanges();
return this.tenancyOffer$.pipe(
map((tenancyOffer) => {
if (tenancyOffer.status === 'incomplete'
&& tenancyOffer.agreement.status === 'incomplete') {
return true;
} else {
this._router.navigate(['/' + Landlord.base, Landlord.manage.base, Landlord.manage.applications.base, route.params.propId, Landlord.manage.applications.summary, route.params.offerId]);
}
})
);
}
GetTenancyOfferById:
this.tenancyOfferCollection = afs.collection<any>('tenancy_offers');
getTenancyOfferById(id: string) {
return this.tenancyOfferCollection.doc(id);
}
错误来自这一部分:tenancyOffer.agreement.status === 'incomplete'
,表示为TypeError: Cannot read property 'status' of undefined.
我调用的HTTP函数在这里,在订阅中路由到这个组件:
landlordAcceptReferences() {
this.hasAcceptedRefs = true;
this.processingAcceptRefs = true;
this._references.landlordAcceptReferences(this.offerId).pipe(
finalize(() => {
this.processingAcceptRefs = false;
})
).subscribe(e => {
console.log({e});
this.dref.close();
this._toastr.success(`You have accepted tenant references`);
this._router.navigate(['../../', Landlord.manage.applications.agreement.base, this.offerId], {relativeTo: this._activatedRoute});
}, () => this.hasAcceptedRefs = false);
}
我将云函数的响应设置为整个firestore文档,其中包含一个协议对象,该对象被记录为console.log({e});
。然后,我将文档的值记录(在此之后),但它并不存在,即使这是我再次调用firestore的地方?
有人知道为什么guard中的getTenancyOfferById(route.params.offerId)
函数没有从firestore返回此文档的最新版本,即使云函数需要在订阅中路由之前结束吗?
发布于 2020-12-04 18:24:40
我猜this.tenancyOfferCollection = afs.collection<any>('tenancy_offers');
是在您的服务中定义的。如果为真,则在加载应用程序后将立即加载该集合。
我建议将tenancy_offers
值存储在您的服务中,并从您的守卫那里读取它。
服务:
export class YourService {
private tenancyOfferMap: Map<string, any> = new Map();
constructor(
private afs: AngularFirestore,
) {
afs.collection<any>('tenancy_offers').snapshotChanges()
.subscribe( actions => {
actions.map( action => {
this.tenancyOfferMap.set(action.payload.doc.id, action.payload.doc.data());
});
});
}
getTenancyOfferById(id: string) {
return this.tenancyOfferMap.get(id);
}
}
防护:
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
const tenancyOffer = this.yourService.getTenancyOfferById(route.params.offerId);
if (tenancyOffer.status === 'incomplete'
&& tenancyOffer.agreement.status === 'incomplete') {
return true;
} else {
return this._router.navigate(['/' + Landlord.base, Landlord.manage.base, Landlord.manage.applications.base, route.params.propId, Landlord.manage.applications.summary, route.params.offerId]);
}
}
发布于 2020-12-04 23:14:56
这可能取决于您的流没有完成的事实。
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
this.tenancyOffer$ = this._tenancyOffer.getTenancyOfferById(route.params.offerId).get({source: 'server'})).valueChanges()
.pipe(take(1)); // <-- ensure your stream completes in guards
return this.tenancyOffer$.pipe(
map((tenancyOffer) => {
if (tenancyOffer && tenancyOffer.status === 'incomplete'
&& tenancyOffer.agreement.status === 'incomplete') {
return true;
} else {
this._router.navigate(['/' + Landlord.base, Landlord.manage.base, Landlord.manage.applications.base, route.params.propId, Landlord.manage.applications.summary, route.params.offerId]);
return false; // <-- always return something in guards
}
})
);
}
https://stackoverflow.com/questions/65140663
复制相似问题