简体   繁体   English

Angular 当最终结果为真时,Router Guard 未解析

[英]Angular Router Guard not resolving when the end result is true

The following code works correctly when the final if statement is true.当最终的 if 语句为真时,以下代码可以正常工作。 Does not ever resolve the requested route when the final if statement is false.当最终 if 语句为 false 时,永远不会解析请求的路由。 I've tried adding awaits and asyncs.我试过添加等待和异步。 I've tried moving the code into a separate function that returns an await with a boolean and nothing is working to resolve the route when it should.我已经尝试将代码移动到一个单独的 function 中,该代码返回一个带有 boolean 的 await 并且没有任何东西可以解决应该解决的问题。 It always works when it should reject an redirect to settings.当它应该拒绝重定向到设置时它总是有效。

If Statement如果语句

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;

Full Router Guard完整的路由器防护

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;
                  });
                });
              });
            }
          });
        });
      }
    });
  }
  
}

As per Angular's implementation, the canActivate method (required by the CanActivate interface) requires a return type.根据 Angular 的实现, canActivate方法( CanActivate接口需要)需要一个返回类型。

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

Without trying to dive to deep into the logic of your route guard, what I can see is that you're not actually returning anything.无需深入研究路由守卫的逻辑,我能看到的是您实际上并没有返回任何东西。 Because userData is an Observable, the subscription logic is handled asynchronously.因为userData是一个 Observable,所以订阅逻辑是异步处理的。 This means that the canActivate method is invoked by the router, the subscription logic is started asynchronously and then the method call resolves with no value.这意味着canActivate方法由路由器调用,订阅逻辑异步启动,然后方法调用解析为无值。

To fix the issue, you'll need to return an Observable stream which contains the boolean. For this I would suggest using rxjs .pipe() in conjunction with the .switchMap() operator in order to preserve the subscription logic.要解决此问题,您需要返回一个包含 boolean 的 Observable stream。为此,我建议将 rxjs .pipe().switchMap()运算符结合使用,以保留订阅逻辑。

return this.authService.userData.pipe(
    switchMap((user) => {
        // Handle subscription logic and return observable of a boolean value
        return this.someService.doSomething();
    })
);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM