此bounty已结束.回答此问题可获得+50声望奖励。赏金宽限期13小时后结束。Rok Benko希望吸引更多的注意力这个问题:**请参阅下面的EDIT 2
(特别是GIF来看看发生了什么).**赏金将奖励给一个谁会给予我一个解决方案,使我的auth guard开始在所有三种情况下正常工作:1)当我点击按钮时(当前工作),2)当我在搜索栏中键入URL时(当前不工作),3)当我刷新页面时(当前不工作)。我不明白为什么现在只有这一种方法有效。
我正在使用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;
}
})
);
};
字符串
截图:
x1c 0d1x的数据
我所尝试的
我尝试在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”|UrlTree| Observable<Boolean|网站Map|Promise<boolean| UrlTree>'。
7导出常量IfSignedIn:CanActivateFn =(route,state)=> {
提问
使用pipe()
时,为什么从Observable
获取undefined
?
编辑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;
}
})
);
};
型
编辑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()
工作,所以我在控制台中没有得到任何东西。
同样的事情也发生在页面刷新上。看来身份验证保护在页面刷新时不起作用。
截图:
的
编辑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) {}
}
型
1条答案
按热度按时间fafcakar1#
你的问题在别处。正如您所看到的,您得到一个
undefined
作为订阅的第一个值。通过执行
subscribe
而不关闭它,它的使用寿命比CanActivateFn
长。我的猜测是,你正在经历一个竞争条件。您的observable发出的状态对于
CanActivateFn
来说太晚了。你的
getSignInStatusObserver
不应该发出undefined
,你过滤它pipe(filter(status => status !== undefined)).
这应该解决你的问题!