我在我的角(10)应用程序中发送多个API请求。如果其中一个请求返回状态401的响应,我希望将页面重定向到我的登录页面(从组件页面)。
我有一个负责API调用的服务,它有以下两个方法:
export class ApiService {
constructor(private http: HttpClient){
}
public get<T>(path: string, params: HttpParams = new HttpParams(), headers: HttpHeaders = new HttpHeaders()): Observable<T> {
return this.getBodyOfResponseOrRedirect(
this.http.get<T>(path, {headers, params, observe: 'response'}));
}
private getBodyOfResponseOrRedirect<T>(responseObservable: Observable<HttpResponse<T>>): Observable<T> {
return responseObservable.pipe(map(response => {
if (response.status === 401) {
window.location.href = 'https://custom-url';
} else {
return response.body;
}
}));
}现在,我尝试在另一个服务中使用API服务方法:
export class ShopDataService{
...
getShopsData(): Observable<Shop[]> {
return this.apiService.get<Shop[]>("https://shops.com/v1/endpoint)
.pipe(
tap(data => console.log('shop recieved : ' + JSON.stringify(data))),
catchError(this.handleError)
);
}
private handleError(err: HttpErrorResponse) {
let errorMessage = '';
errorMessage = `Server returned code : ${err.status}, error message is : ${err.message}`;
console.error(errorMessage);
return throwError(errorMessage);
}当响应状态为401时,重定向无法工作,相反,我在控制台中看到:
main.gb7558h03a743440f512.js:1服务器返回代码: 401,错误消息是:https://shops.com/v1/endpoint的Http失败响应: 401 OK
我做错什么了?
这里的主要想法是,当我加载组件时,我的auth令牌是有效的。过了一段时间,我的令牌过期了,但我没有刷新或移动到另一个页面。因此,当前的页面功能可能发送带有无效令牌的api请求,并将得到401错误的响应。我想处理一下这种行为。
发布于 2020-11-17 14:43:00
该401未经授权的响应通常以error通知的形式从角HttpClient发出。因此,您需要使用RxJS catchError操作符来捕获错误并重定向。然后,您可以发出NEVER常数,以便在重定向之后没有任何东西发出,并保持可观察到的活动,或者发出EMPTY常数来完成可观测的操作。
尝试以下几点
import { throwError, NEVER } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
export class ApiService {
constructor(private http: HttpClient) { }
public get<T>(
path: string,
params: HttpParams = new HttpParams(),
headers: HttpHeaders = new HttpHeaders()
): Observable<T> {
return this.getBodyOfResponseOrRedirect(
this.http.get<T>(path, {headers, params, observe: 'response'}));
}
private getBodyOfResponseOrRedirect<T>(
responseObservable: Observable<HttpResponse<T>>
): Observable<T> {
return responseObservable.pipe(
catchError(error => {
if (!!error.status && error.status === 401) {
window.location.href = 'https://custom-url';
return NEVER; // <-- never emit after the redirect
}
return throwError(error); // <-- pass on the error if it isn't 401
}),
map(response => response.body)
);
}
}发布于 2020-11-18 13:00:13
@Michael解决方案非常有用。根据他的评论,我实现了以下http拦截器:
@Injectable()
export class HttpResponseInterceptor implements HttpInterceptor {
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request).pipe(catchError(error => {
if (!!error.status && error.status === 401) {
window.location.href = 'url';
return NEVER;
}
return throwError(error);
}));
}
}https://stackoverflow.com/questions/64877273
复制相似问题