使用 tap() 而不是 map() RxJS 和 Angular

Use tap() instead of map() RxJS and Angular

我有一个登录守卫,主要检查用户是否登录。如果他登录了,它会跳过登录并转到主页。我写了这段代码,效果很好:

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    return this.store.select(fromApp.isAuthenticated)
        .pipe(take(1),
            map(isAuthenticated => {
                if (isAuthenticated) {
                    this.router.navigate(['/home']);
                    return false;
                } else {
                    return true;
                }
            })
        )
}

现在,由于我不必更改或编辑输出数据(isAuthenticated 布尔值),我想:好吧,为什么不使用 tap 运算符?所以,我重写了我的代码:

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    return this.store.select(fromApp.isAuthenticated)
        .pipe(take(1),
   HERE------> tap(isAuthenticated => {   <------ HERE
                if (isAuthenticated) {
                    this.router.navigate(['/home']);
                    return false;
                } else {
                    return true;
                }
            })
        )
}

然后我去了Chrome,看到黑页是这样的:

无论如何,我看到的是空白页。所以,我进行了调试,我注意到它正确地跳入了 if/else 块内……那么,为什么 tap() 会破坏应用程序?

ThiscanActivate的签名:

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

canActivate 必须 return booleanPromise。因此你必须map它和return一个booleanPromisetap 不会成功。

守卫 canActivate 必须 return 一个 Observable<boolean> 才能使 Angular 守卫机制工作。

使用 map 允许您定义一个 return,它不同于您从 isAuthenticated 得到的,这可能解释了您所看到的。

在你的第一个版本中 canActivate 实际上 return 是一个 Observable<boolean> - 在第二种情况下它 return 是这个 this.store.select(fromApp.isAuthenticated).pipe(take(1)) ,并且可能是不是你想要的。