我正在使用 PEAN 堆栈(即 PostgreSQL - ExpressJS - Angular - NodeJS)构建一个身份验证应用程序。
Problem
我的身份验证守卫有问题:
- 如果我使用
subscribe()
,我在控制台中得到了预期的结果。✔ - 工作
- 如果我使用
pipe()
, I get 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()
:
if-signed-in.guard.ts
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 - 错误 TS2322:类型
'(路由:ActivatedRouteSnapshot,状态:RouterStateSnapshot)=> void'
不可分配给类型“CanActivateFn”。类型“void”不是
可分配给类型 'boolean |网址树 |可观察
|承诺'.
7 导出 const IfSignedIn: CanActivateFn = (路由, 状态) => {
Question
为什么我得到不明确的使用时从 authguard 中的 Observablepipe()
, while subscribe()
有效,但我收到错误?
EDIT 1
我已经尝试了 @MatthieuRiegler 建议的代码,但我仍然得到与上面的屏幕截图完全相同的响应。
if-signed-in.guard.ts
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;
}
})
);
};
EDIT 2
我的应用程序表现得很奇怪。现在我有以下代码:
if-signed-in.guard.ts
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()
有效,我在控制台中没有得到任何东西。
此外,页面刷新时也会发生同样的情况。似乎身份验证防护在页面刷新时不起作用。
截屏:
EDIT 3
我使用拦截器设置登录状态,如下所示:
登录状态.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) {}
}