使用承诺 return 来自 HTTP 拦截器的请求对象
Using a promise to return a request object from an HTTP interceptor
几个小时以来,我一直在摸不着头脑,我希望有人能帮助我并指导我。因此,我正在开发一个 Angular 7 应用程序身份验证模块。其中一项要求是开发一个 HTTP 拦截器以添加授权 (JWT) 令牌并处理所有错误消息。
我正在使用 NPM 包来处理令牌的本地存储。此包使用 set 和 get 方法来存储和 returns 承诺而不是令牌的实际值。
现在,我的问题出在我的拦截器函数中,如下所示。我试图评论我卡住的地方。
intercept(request: HttpRequest<any>, next: HttpHandler):
Observable<HttpEvent<any>> {
// Trying to get the token here but this returns a promise
// this.token is a service for managing storage and retrieving of tokens
const token = this.token.getToken();
// If token is got, set it in the header
// But when i console log, i see [object promise] other than the token
if (token) {
request = request.clone({
headers: request.headers.set('Authorization', 'Bearer ' + token)
});
}
return next.handle(request).pipe(catchError(err => {
// Logs out the user if 401 error
if (err.status === 401) {
this.token.remove()
.then(() => {
this.auth.changeAuthStatus(false);
this.router.navigateByUrl('/login');
});
}
// Returns the error message for the user to see
// for example in an alert
const error = err.error.message || err.statusText;
return throwError(error);
}));
}
希望我已经很好地解释了这个问题。我曾尝试在拦截器函数之前使用 async
,但我收到一个红色的讨厌错误,提示 TS1055: Type 'typeof Observable' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value. Types of parameters 'subscribe' and 'executor' are incompatible.
.
对于解决此问题的任何帮助,我将不胜感激。
谢谢!
要将异步处理合并到您的拦截器中,您希望将您的承诺提升为一个可观察对象,并且 switchMap
您的可观察对象一起返回正确的请求:
import { from as observableFrom } from "rxjs";
import { switchMap } from "rxjs/operators";
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return observableFrom(this.token.getToken()).pipe(
switchMap(token => {
// do something with your promise-returned token here
return next.handle(request).pipe(catchError(err => {
// Logs out the user if 401 error
if (err.status === 401) {
this.token.remove()
.then(() => {
this.auth.changeAuthStatus(false);
this.router.navigateByUrl('/login');
});
}
// Returns the error message for the user to see
// for example in an alert
const error = err.error.message || err.statusText;
return throwError(error);
}));
})
);
}
尚未直接测试此代码,因此对于任何拼写错误我深表歉意,但它应该可以让您到达您想去的地方。
1) 通过 from
将您的承诺提升为可观察对象
2) 用 switchMap
链接你的 observables
我注意到您实际上并没有使用示例中返回的令牌,您可以在 switchMap 中接收承诺结果的函数中执行此操作
尝试直接从本地存储中获取令牌。为此,当您使用令牌服务方法获取令牌时,将该令牌存储到本地存储。
试试下面的代码:
token.service.ts
setToken(token) {
localStorage.setItem('app-token', JSON.stringify(token));
}
getToken() {
return JSON.parse(localStorage.getItem('app-token'));
}
拦截器代码
intercept(request: HttpRequest<any>, next: HttpHandler):
Observable<HttpEvent<any>> {
//This token is retrieved from local storage
const token = this.token.getToken();
// If token is got, set it in the header
// But when i console log, i see [object promise] other than the token
if (token) {
request = request.clone({
headers: request.headers.set('Authorization', 'Bearer ' + token)
});
}
return next.handle(request).pipe(catchError(err => {
// Logs out the user if 401 error
if (err.status === 401) {
this.token.remove()
.then(() => {
this.auth.changeAuthStatus(false);
this.router.navigateByUrl('/login');
});
}
// Returns the error message for the user to see
// for example in an alert
const error = err.error.message || err.statusText;
return throwError(error);
}));
}
几个小时以来,我一直在摸不着头脑,我希望有人能帮助我并指导我。因此,我正在开发一个 Angular 7 应用程序身份验证模块。其中一项要求是开发一个 HTTP 拦截器以添加授权 (JWT) 令牌并处理所有错误消息。
我正在使用 NPM 包来处理令牌的本地存储。此包使用 set 和 get 方法来存储和 returns 承诺而不是令牌的实际值。
现在,我的问题出在我的拦截器函数中,如下所示。我试图评论我卡住的地方。
intercept(request: HttpRequest<any>, next: HttpHandler):
Observable<HttpEvent<any>> {
// Trying to get the token here but this returns a promise
// this.token is a service for managing storage and retrieving of tokens
const token = this.token.getToken();
// If token is got, set it in the header
// But when i console log, i see [object promise] other than the token
if (token) {
request = request.clone({
headers: request.headers.set('Authorization', 'Bearer ' + token)
});
}
return next.handle(request).pipe(catchError(err => {
// Logs out the user if 401 error
if (err.status === 401) {
this.token.remove()
.then(() => {
this.auth.changeAuthStatus(false);
this.router.navigateByUrl('/login');
});
}
// Returns the error message for the user to see
// for example in an alert
const error = err.error.message || err.statusText;
return throwError(error);
}));
}
希望我已经很好地解释了这个问题。我曾尝试在拦截器函数之前使用 async
,但我收到一个红色的讨厌错误,提示 TS1055: Type 'typeof Observable' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value. Types of parameters 'subscribe' and 'executor' are incompatible.
.
对于解决此问题的任何帮助,我将不胜感激。
谢谢!
要将异步处理合并到您的拦截器中,您希望将您的承诺提升为一个可观察对象,并且 switchMap
您的可观察对象一起返回正确的请求:
import { from as observableFrom } from "rxjs";
import { switchMap } from "rxjs/operators";
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return observableFrom(this.token.getToken()).pipe(
switchMap(token => {
// do something with your promise-returned token here
return next.handle(request).pipe(catchError(err => {
// Logs out the user if 401 error
if (err.status === 401) {
this.token.remove()
.then(() => {
this.auth.changeAuthStatus(false);
this.router.navigateByUrl('/login');
});
}
// Returns the error message for the user to see
// for example in an alert
const error = err.error.message || err.statusText;
return throwError(error);
}));
})
);
}
尚未直接测试此代码,因此对于任何拼写错误我深表歉意,但它应该可以让您到达您想去的地方。
1) 通过 from
2) 用 switchMap
我注意到您实际上并没有使用示例中返回的令牌,您可以在 switchMap 中接收承诺结果的函数中执行此操作
尝试直接从本地存储中获取令牌。为此,当您使用令牌服务方法获取令牌时,将该令牌存储到本地存储。
试试下面的代码:
token.service.ts
setToken(token) {
localStorage.setItem('app-token', JSON.stringify(token));
}
getToken() {
return JSON.parse(localStorage.getItem('app-token'));
}
拦截器代码
intercept(request: HttpRequest<any>, next: HttpHandler):
Observable<HttpEvent<any>> {
//This token is retrieved from local storage
const token = this.token.getToken();
// If token is got, set it in the header
// But when i console log, i see [object promise] other than the token
if (token) {
request = request.clone({
headers: request.headers.set('Authorization', 'Bearer ' + token)
});
}
return next.handle(request).pipe(catchError(err => {
// Logs out the user if 401 error
if (err.status === 401) {
this.token.remove()
.then(() => {
this.auth.changeAuthStatus(false);
this.router.navigateByUrl('/login');
});
}
// Returns the error message for the user to see
// for example in an alert
const error = err.error.message || err.statusText;
return throwError(error);
}));
}