在 Angular 路由守卫中等待 return 的值
Waiting for a value to return in Angular route guards
我在 Angular 中使用 Ionic。
在我的一个路由守卫中,我需要查看是否创建了一个 firestore 文档以及 return 它的一个布尔值,这需要一些时间才能从服务器获得响应,但是路由守卫不会等待为return的值并正常运行,所以页面没有被保护!
我怎样才能让路由守卫等待价值?
或者,return路由守卫运行前的值?
这是我向 firestore 发送请求的地方:
export class FirebaseService {
ex: Promise<boolean>;
categoryDone: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
constructor(private afs: AngularFirestore) {
this.ex = new Promise((resolve) => {
this.afs.collection('users').doc(this.user.uid).collection('categories').get().toPromise().then(
data => {
if (data.size > 0) {
resolve(true)
} else {
resolve(false)
}
}
)
})
this.ex.then(data=>{
if (data) {
this.categoryDone.next(true)
} else {
this.categoryDone.next(false)
}
})
}
这是我的路由守卫代码,我将它用于我的页面:
export class CategoryDoneGuard implements CanActivate {
categoryDone: boolean;
constructor(private router: Router, private firebaseService: FirebaseService) {
this.firebaseService.categoryDone.asObservable().subscribe(
categoryDone => this.categoryDone = categoryDone
)
}
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> | boolean {
console.log(this.categoryDone,"Category Done VAriable in CategoryDoneGuard")
setTimeout(() => {
console.log(this.categoryDone,"Catgeory") //true because i waited 1 second
}, 1000);
if (!this.categoryDone) { //variable is undefined here
console.log('You are in InfoDoneGuard')
return true
}
this.router.navigate(['tabs/tab-profile'])
return false
}
}
不要 return 布尔值,return Observable!
导出class CategoryDoneGuard 实现 CanActivate {
constructor(
private router: Router,
private firebaseService: FirebaseService
) { }
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot,
): Observable<boolean> {
return this.firebaseService.categoryDone.asObservable().pipe(
map(Boolean),
tap(b => if (!b) this.router.navigate(['tabs/tab-profile'] ),
);
}
就像在其他答案中一样,auth guard 可以接受布尔值、可观察值或布尔值或 urltree 的承诺。但我会稍微重组整个服务功能,除非你需要 categoryDone
做其他事情,但如果你需要的话,你可以在你的服务中添加它。
但就您的服务目前而言,您在调用 toPromise()
的同时也创建了一个新的承诺,这实际上没有任何意义。
我会做...
服务:
// please choose a more suitable name :D
getBool() {
return this.afs.collection('users').doc(this.user.uid).collection('categories').get().pipe(
map(data => data.size > 0),
// if you need
// tap(bool => this.categoryDone.next(bool))
)
}
可以激活:
canActivate(...): Observable<boolean> {
return this.firebaseService.getBool().pipe(
map(bool => {
if (bool) {
return true;
}
this.router.navigate(['tabs/tab-profile'])
return false;
})
)
}
但是如果 categoryDone
在您的应用程序中对您来说必不可少,您也可以像 MoxxiManagarm 的回答一样在 authguard 中订阅它。无论如何,我会重组 firebase 查询以删除 promise 内容。
我在 Angular 中使用 Ionic。 在我的一个路由守卫中,我需要查看是否创建了一个 firestore 文档以及 return 它的一个布尔值,这需要一些时间才能从服务器获得响应,但是路由守卫不会等待为return的值并正常运行,所以页面没有被保护! 我怎样才能让路由守卫等待价值? 或者,return路由守卫运行前的值? 这是我向 firestore 发送请求的地方:
export class FirebaseService {
ex: Promise<boolean>;
categoryDone: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
constructor(private afs: AngularFirestore) {
this.ex = new Promise((resolve) => {
this.afs.collection('users').doc(this.user.uid).collection('categories').get().toPromise().then(
data => {
if (data.size > 0) {
resolve(true)
} else {
resolve(false)
}
}
)
})
this.ex.then(data=>{
if (data) {
this.categoryDone.next(true)
} else {
this.categoryDone.next(false)
}
})
}
这是我的路由守卫代码,我将它用于我的页面:
export class CategoryDoneGuard implements CanActivate {
categoryDone: boolean;
constructor(private router: Router, private firebaseService: FirebaseService) {
this.firebaseService.categoryDone.asObservable().subscribe(
categoryDone => this.categoryDone = categoryDone
)
}
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> | boolean {
console.log(this.categoryDone,"Category Done VAriable in CategoryDoneGuard")
setTimeout(() => {
console.log(this.categoryDone,"Catgeory") //true because i waited 1 second
}, 1000);
if (!this.categoryDone) { //variable is undefined here
console.log('You are in InfoDoneGuard')
return true
}
this.router.navigate(['tabs/tab-profile'])
return false
}
}
不要 return 布尔值,return Observable!
导出class CategoryDoneGuard 实现 CanActivate {
constructor(
private router: Router,
private firebaseService: FirebaseService
) { }
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot,
): Observable<boolean> {
return this.firebaseService.categoryDone.asObservable().pipe(
map(Boolean),
tap(b => if (!b) this.router.navigate(['tabs/tab-profile'] ),
);
}
就像在其他答案中一样,auth guard 可以接受布尔值、可观察值或布尔值或 urltree 的承诺。但我会稍微重组整个服务功能,除非你需要 categoryDone
做其他事情,但如果你需要的话,你可以在你的服务中添加它。
但就您的服务目前而言,您在调用 toPromise()
的同时也创建了一个新的承诺,这实际上没有任何意义。
我会做...
服务:
// please choose a more suitable name :D
getBool() {
return this.afs.collection('users').doc(this.user.uid).collection('categories').get().pipe(
map(data => data.size > 0),
// if you need
// tap(bool => this.categoryDone.next(bool))
)
}
可以激活:
canActivate(...): Observable<boolean> {
return this.firebaseService.getBool().pipe(
map(bool => {
if (bool) {
return true;
}
this.router.navigate(['tabs/tab-profile'])
return false;
})
)
}
但是如果 categoryDone
在您的应用程序中对您来说必不可少,您也可以像 MoxxiManagarm 的回答一样在 authguard 中订阅它。无论如何,我会重组 firebase 查询以删除 promise 内容。