假设相同的代码导致不同的路由行为

时间:2018-12-30 07:27:28

标签: javascript angular typescript

我正在开发一个Web应用程序,并在Angular前端代码中定义了以下isLoggedIn()函数来检查用户是否已通过身份验证:

@Injectable()
export class AuthService {

    // irrelevant code is omitted for brevity

    private currentUserSubject = new BehaviorSubject<User>(
        JSON.parse(localStorage.getItem(AuthService.KEY_USER))
    );

    isLoggedIn(): boolean {
        return this.currentUserSubject.value &&
            (this.currentUserSubject.value.expiresAtMillis > Date.now());
    }
}

在我的路由模块中,我具有以下路由定义:

{ path: ':id', component: DetailsComponent, canActivate: [AuthGuard, IdGuard] }

AuthGuard检查用户是否登录:

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
    if (this.authService.isLoggedIn()) {
        return true;
    }
    return false;
}

然后IdGuard检查id参数是否为数字:

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
    if (isNaN(Number(route.paramMap.get('id')))) {
        return false;
    }
    return true;
}

这一切正常,仅当用户通过身份验证并且id参数是一个数字时,该路由才可以访问。

当我将AuthGuard代码更改为更惯用时,就会发生问题:

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {

    // old code
    // if (this.authService.isLoggedIn()) {
    //     return true;
    // }
    // return false;

    // new code
    return this.authService.isLoggedIn();
}

使用此新代码,即使用户未未通过认证,也可以访问该路由。

如果我从路线中删除了IdGuard(因此仅应用了AuthGuard),那么它可以正常工作,,所以我猜想它必须与这两个后卫如何互动彼此,但我无法找出确切的问题。

如果有人能向我解释这种行为,我将非常感激。

编辑

我认为我已经找到问题了。如果currentUserSubject.valuenull,则以下表达式返回null而不是truefalse

return this.currentUserSubject.value &&
    (this.currentUserSubject.value.expiresAtMillis > Date.now());

因此,以下各项按预期工作:

// checking explicitly for null
return this.currentUserSubject.value == null &&
    (this.currentUserSubject.value.expiresAtMillis > Date.now());

这也是:

// converting to Boolean
return Boolean(this.currentUserSubject.value) &&
    (this.currentUserSubject.value.expiresAtMillis > Date.now());

但是为什么会这样呢?

在这样的表达式中使用this.currentUserSubject.value是否应该自动转换为Boolean值吗?

1 个答案:

答案 0 :(得分:2)

要在编辑中回答问题:

逻辑运算符&&||并不总是返回布尔值:

    如果 A falsy,则
  • A && B返回值 A 。否则,它返回 B
  • 如果 A truthy,则
  • A || B返回值 A 。否则,它返回 B

一些例子:

  • null && truenull
  • "hello" || false"hello"
  • 1 && 22
  • 0 || undefinedundefined

可以在MDN上找到更多示例。