[英]Angular wait for method to finish
我有 HTTP 拦截器拦截 http 请求 api
首先它检查这个 api 是否需要授权,然后检查 session 变量以查看是否已经保存了令牌并检查它是否有效
如果没有令牌或令牌已过期,则应获取新令牌,然后照常进行
代码 rest 在检索令牌之前执行,然后它不添加所需的身份验证 header。我不知道如何让它等待。
intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
let authReq = request;
const token = this.checkUrl(authReq.url)
if (token){
authReq = request.clone({
headers: request.headers.set(this.TOKEN_HEADER_KEY, 'Bearer ' + token)
});
}
return next.handle(authReq);
}
获取令牌并检查是否需要身份验证的checkUrl
方法
checkUrl(url: string): string {
if (url.includes('/login')){
return ''
}
for (let x of this.includedList) {
if (url.includes(x.url)){
return this.auth.getApiToken()
//break;
}
}
return ''
}
从 session 存储或登录端点获取令牌的getApiToken
方法
getApiToken(): string{
let token = <string>sessionStorage.getItem('auth-token');
if (!token || this.jwt.isTokenExpired(token)){
this.apiLogin().subscribe({
next: data => {
console.log(data)
sessionStorage.setItem("auth-token", data.token)
token = data.token
},
error: err => {
console.log(err)
token = ''
}
})
}
return token;
}
最后是从 api 获取新令牌的apiLogin
方法
apiLogin(): Observable<any> {
const loginData = {
username: environment.apiLoginData.username,
password: environment.apiLoginData.password
}
return this.http.post(AUTH_API, loginData);
}
编辑
我尝试使用 Observable 和 map 的解决方案
interceptor
intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
let authReq = request;
let token = ''
this.checkUrlV2(authReq.url).pipe(map(data => {
console.log(data)
token = data
}));
console.log('token')
console.log(token)
if (token){
authReq = request.clone({
headers: request.headers.set(this.TOKEN_HEADER_KEY, 'Bearer ' + token)
});
}
return next.handle(authReq);
}
checkUrlV2
checkUrlV2(url: string): Observable<string> {
if (url.includes('/login')){
return of('')
}
for (let x of this.includedList) {
if (url.includes(x.url)){
this.auth.apiTokenV2().pipe(map(data => {
console.log(data)
return of(data)
}));
//break;
}
}
return of('')
}
apiTokenV2
apiTokenV2() {
let token = ''
if (!token || this.jwt.isTokenExpired(token)){
this.apiLogin().pipe(map(data => {
console.log(data)
sessionStorage.setItem("auth-token", data.token)
return of(data.token)
}));
}
return of(token)
}
找到适合我的案例的解决方案。 它确实在不检查令牌的情况下请求,如果出现错误则刷新它
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
req = this.addAuthenticationToken(req);
return <Observable<HttpEvent<any>>>next.handle(req).pipe(
catchError((error: HttpErrorResponse) => {
if (error && error.status === 401) {
if (this.refreshTokenInProgress) {
// If refreshTokenInProgress is true, we will wait until refreshTokenSubject has a non-null value which means the new token is ready and we can retry the request again
return this.refreshTokenSubject.pipe(
filter(result => result !== null),
take(1),
switchMap(() => next.handle(this.addAuthenticationToken(req)))
);
} else {
this.refreshTokenInProgress = true;
// Set the refreshTokenSubject to null so that subsequent API calls will wait until the new token has been retrieved
this.refreshTokenSubject.next(null);
return this.refreshAccessToken().pipe(
switchMap((success: boolean) => {
this.refreshTokenSubject.next(success);
return next.handle(this.addAuthenticationToken(req));
}),
// When the call to refreshToken completes we reset the refreshTokenInProgress to false for the next time the token needs to be refreshed
finalize(() => this.refreshTokenInProgress = false)
);
}
} else {
return throwError(() => new Error(error.message));
}
})
);
}
private refreshAccessToken(): Observable<any> {
return this.auth.apiLogin().pipe(map(authData => {
console.log('Token refreshed')
sessionStorage.setItem("auth-token", authData.token)
return authData.token
}))
}
private addAuthenticationToken(request: HttpRequest<any>): HttpRequest<any> {
const token = <string>sessionStorage.getItem('auth-token')
for (let x of this.excludedUrl){
if (request.url.includes(x)){
return request;
}
}
for (let x of this.includedList) {
if (request.url.includes(x.url)){
console.log('Bearer token added')
return request.clone({
headers: request.headers.set(this.TOKEN_HEADER_KEY, 'Bearer ' + token)
});
}
}
return request;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.