You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular路由守卫中pipe()返回undefined,subscribe()可用却报错

PEAN栈认证应用路由守卫问题排查

我正在使用PEAN栈(PostgreSQL - ExpressJS - Angular - NodeJS)开发一款认证应用。

问题

我的路由守卫(auth guard)存在如下问题:

  • 使用subscribe()时,控制台能输出预期结果。✔ 可用
  • 使用pipe()时,控制台输出undefined。✖ 不可用

if-signed-in.guard.ts

import { CanActivateFn } from '@angular/router';
import { AuthService } from '../services/auth/auth.service';
import { inject } from '@angular/core';
import { tap, map } from 'rxjs/operators';
import { Router } from '@angular/router';

export const IfSignedIn: CanActivateFn = (route, state) => {
  const auth = inject(AuthService);
  const router = inject(Router);
    
  auth.getSignInStatusObserver().subscribe((res: any) => {
    console.log(res);
  });

  return auth.getSignInStatusObserver().pipe(
    tap((status) => {
      console.log(status);
    }),
    map((status) => {
      console.log(status);
      if (status) {
        if (status.success === true) {
          return true;
        } else {
          router.navigate(['/dashboard']);
          return false;
        }
      } else {
        router.navigate(['/dashboard']);
        return false;
      }
    })
  );
};

控制台截图:
控制台输出截图

已尝试方案

我尝试将逻辑移入subscribe()中,修改后的代码如下:

import { CanActivateFn } from '@angular/router';
import { AuthService } from '../services/auth/auth.service';
import { inject } from '@angular/core';
import { Router } from '@angular/router';

export const IfSignedIn: CanActivateFn = (route, state) => {
  const auth = inject(AuthService);
  const router = inject(Router);

  auth.getSignInStatusObserver().subscribe((res: any) => {
    if (res) {
      if (res.success === true) {
        return true;
      } else {
        router.navigate(['/dashboard']);
        return false;
      }
    } else {
      router.navigate(['/dashboard']);
      return false;
    }
  });
};

但出现如下编译错误:

src/app/auth/guards/if-signed-in.guard.ts:7:14 - error TS2322: Type
'(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => void'
is not assignable to type 'CanActivateFn'. Type 'void' is not
assignable to type 'boolean | UrlTree | Observable<boolean | UrlTree>
| Promise<boolean | UrlTree>'.

7 export const IfSignedIn: CanActivateFn = (route, state) => {

核心问题

为什么在路由守卫中使用pipe()时Observable返回undefined,而subscribe()能得到结果却报错?


编辑1

我尝试了@MatthieuRiegler建议的代码,添加了filter操作符过滤undefined值,但仍得到和之前一样的结果。修改后的代码:

import { CanActivateFn } from '@angular/router';
import { AuthService } from '../services/auth/auth.service';
import { inject } from '@angular/core';
import { filter, tap, map } from 'rxjs/operators';
import { Router } from '@angular/router';

export const IfSignedIn: CanActivateFn = (route, state) => {
  const auth = inject(AuthService);
  const router = inject(Router);

  auth.getSignInStatusObserver().subscribe((res: any) => {
    console.log(res);
  });

  return auth.getSignInStatusObserver().pipe(
    filter((status) => status !== undefined),
    tap((status) => {
      console.log(status);
    }),
    map((status) => {
      console.log(status);
      if (status) {
        if (status.success === true) {
          return true;
        } else {
          router.navigate(['/dashboard']);
          return false;
        }
      } else {
        router.navigate(['/dashboard']);
        return false;
      }
    })
  );
};

编辑2

应用表现异常,当前代码如下:

import { CanActivateFn } from '@angular/router';
import { AuthService } from '../services/auth/auth.service';
import { inject } from '@angular/core';
import { filter, tap, map } from 'rxjs/operators';
import { Router } from '@angular/router';

export const IfSignedIn: CanActivateFn = (route, state) => {
  const auth = inject(AuthService);
  const router = inject(Router);

  return auth.getSignInStatusObserver().pipe(
    filter((status) => status !== undefined),
    tap((status) => {
      console.log('Tap: ', status);
    }),
    map((status) => {
      console.log('Map: ', status);
      if (status) {
        if (status.success === true) {
          return true;
        } else {
          router.navigate(['/dashboard']);
          return false;
        }
      } else {
        router.navigate(['/dashboard']);
        return false;
      }
    })
  );
};

点击“编辑资料”按钮时一切正常,但直接在地址栏输入http://localhost:4200/profile/edit-profile或刷新页面时,会收到undefined,且因filter()生效,控制台无输出,路由守卫在页面刷新时失效。

操作演示截图:
页面刷新时路由守卫失效演示


编辑3

我使用拦截器设置登录状态,相关代码如下:
sign-in-status.service.ts

import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpEvent, HttpRequest, HttpHandler, HttpResponse } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { tap, catchError } from 'rxjs/operators';
import { AuthService } from 'src/app/auth/services/auth/auth.service';

@Injectable({
  providedIn: 'root',
})
export class SignInStatusService implements HttpInterceptor {
  intercept(httpRequest: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(httpRequest).pipe(
      tap((event: HttpEvent<any>) => {
        if (event instanceof HttpResponse && httpRequest.url.endsWith('api/get-user') && event.status === 200) {
          this.authService.setSignInStatus({ success: true, response: event.body });
        }
      }),
      catchError((err: any) => {
        if (httpRequest.url.endsWith('api/get-user')) {
          this.authService.setSignInStatus({ success: false, response: err });
        }
        return throwError(() => err);
      })
    );
  }

  constructor(private authService: AuthService) {}
}

内容的提问来源于stack exchange,提问作者Rok Benko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 08:30:09