0

当最后的 if 语句为真时,以下代码可以正常工作。当最终的 if 语句为假时,永远不会解析请求的路由。我试过添加等待和异步。我已经尝试将代码移动到一个单独的函数中,该函数返回一个带有布尔值的等待,并且在它应该解析路由时没有任何工作。当它应该拒绝重定向到设置时,它总是有效。

如果语句

if(moduleSnapshot.size >= planLimit) {
   this.toast.info(`You've reached your plan maximum, upgrade to add more ${mod}.`, 'Plan Maximum');
   this.router.navigateByUrl('/settings/profile/subscription');
   return false;
}
return true;

完整的路由器保护

import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router';
import { Observable } from 'rxjs';

import { ToastrService } from 'ngx-toastr';
import { AngularFirestore } from '@angular/fire/firestore';
import { AuthService } from '../services/auth/auth.service';
import { SubscriptionsService } from '../services/subscriptions/subscriptions.service';

@Injectable({
  providedIn: 'root'
})
export class SubscriptionGuard implements CanActivate {

  constructor( private router: Router, private toast: ToastrService, private authService: AuthService, private subscriptionService: SubscriptionsService, private afs: AngularFirestore ) { }

  canActivate( route: ActivatedRouteSnapshot, state: RouterStateSnapshot ): any {
    this.authService.userData.subscribe((observer1) => {
      if(observer1) {
        let subscriptions = this.subscriptionService.fetchUserSubscription(observer1.uid);
        subscriptions.onSnapshot((observer:any) => {
          observer.forEach((subscription:any) => {
            if(subscription.exists) {
              this.authService.allUserData.subscribe( async(userDataObserver:any) => {
                let mod:string = state.url.split('/')[1];
                await this.subscriptionService.fetchPlan(subscription.data().productID).then((plan:any) => {
                  let planLimit:number = parseInt(plan.metadata[mod]);
                  let companyUid:string = userDataObserver.companies[0].company;
                  this.afs.collection('companies').doc(companyUid).collection(mod).ref.get().then((moduleSnapshot:any) => {
                    if(moduleSnapshot.size >= planLimit) {
                      this.toast.info(`You've reached your plan maximum, upgrade to add more ${mod}.`, 'Plan Maximum');
                      this.router.navigateByUrl('/settings/profile/subscription');
                      return false;
                    }
                    console.log('Plan max not met, should resolve');
                    return true;
                  });
                });
              });
            }
          });
        });
      }
    });
  }
  
}
4

1 回答 1

0

根据 Angular 的实现,canActivate方法(CanActivate接口需要)需要返回类型。

export declare interface CanActivate {
    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree;
}

没有试图深入研究你的路由守卫的逻辑,我可以看到你实际上并没有返回任何东西。因为userData是 Observable,所以订阅逻辑是异步处理的。这意味着该canActivate方法由路由器调用,订阅逻辑异步启动,然后方法调用解析为没有值。

要解决此问题,您需要返回一个包含布尔值的 Observable 流。为此,我建议将 rxjs.pipe().switchMap()运算符结合使用,以保留订阅逻辑。

return this.authService.userData.pipe(
    switchMap((user) => {
        // Handle subscription logic and return observable of a boolean value
        return this.someService.doSomething();
    })
);
于 2021-10-08T02:19:41.643 回答