路由器:从canActivate方法返回的承诺中进行重定向

Router: Redirect from within a promise returned by a `canActivate` method

本文关键字:承诺 重定向 返回 canActivate 方法 路由器      更新时间:2023-09-26

我有几个方法来访问我的服务器。所有这些方法都没有返回承诺或可观察对象,我在传递回调。

现在我需要写一个保护,以确保在用户可以使用多个路由之前已经加载了用户数据。canActivate方法返回一个promise,但是有代码在promise中导航,这不起作用。

有人知道如何解决这个问题吗?我必须重写我的api方法来返回承诺或可观察对象吗?或者有一种方法,使重定向从一个承诺,这是返回我的canActivate。将代码移到resolve对象中获取用户数据(如果用户已登录)会更好吗?

import {Injectable} from '@angular/core';
import {CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot} from '@angular/router';
import {GlobalStateService} from './globalState.service';
import {AuthTokenService} from './authToken.service';
import {UserApi} from '../api/user.api';
@Injectable()
export class AfterLogInGuardService implements CanActivate {
    constructor(
        private globalState: GlobalStateService,
        private authToken: AuthTokenService,
        private router: Router,
        private userApi: UserApi
    ) { }
    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean|Promise<boolean> {
        // The tho user is not logged in, redirect her always to the login page, if
        // she calls routes with this guard.
        if (!this.authToken.has()) {
            this.router.navigateByUrl('/logIn');
            return false;
        }
        const thisGuard = this;
        // If the user has a token, we have to ensure, that we have the user data
        // loaded from the server.
        return this.afterUserDataHasBeenLoaded(function () {
            // Redirect the user to the "Please enter your personal data" page, if
            // she has not entered them yet.
            if (!thisGuard.globalState.personalDataStored && route.url.toString() !== 'signUp,personalData') {
                //
                // This here doesn't work!
                //
                thisGuard.router.navigateByUrl('/signUp/personalData');
                return false;
            }
            return true;
        });
    };
    private afterUserDataHasBeenLoaded(callback: () => boolean) {
        const thisGuard = this;
        return new Promise<boolean>(function(resolve, reject) {
            if (thisGuard.globalState.userDataLoaded)
                return callback();
            const innerCallback = function () {
                thisGuard.globalState.userDataLoaded = true;
                resolve(callback());
            };
            thisGuard.userApi.getUserData(innerCallback);
        });
    }
}

以下实现可能是有用的。承诺在auth.service

中定义

auth.guard

import { Injectable } from '@angular/core';
import { Router, CanActivate } from '@angular/router';
import { AuthService} from './services/auth.service';
@Injectable()
export class AuthGuard implements CanActivate {
      status:boolean=false;
      constructor(private authService:AuthService, private router:Router) { }
      canActivate() {
        var self=this;
        this.authService.isAuth()
        .then((res)=>{if(res==true)return true;else self.router.navigate(['/login']);});
      }
    }

auth.service

isAuth(): Promise<Status> {
  const url = "/account/check";
  return this.http.get(url)
    .toPromise()
    .then(response=>return response.json().status as Status)
    .catch(this.handleError);
}

服务器响应

{_body: "{"status":false}", status: 200, ok: true, statusText: " ok ",标题:标题…}