在我的角度应用程序中,我看到chrome(取消)api调用太快了。我还有一个HttpInterceptor,如果请求没有完成,它会在500ms后触发每个HttpClient请求的加载指示符。但是,在获取(取消)的请求中,似乎没有任何新事件随后隐藏我的加载指示符。
有没有办法在HttpInterceptor中检测'已取消'的请求,以便我可以再次隐藏我的加载指示符?
export class GlobalHttpInterceptor implements HttpInterceptor {
constructor(
private sessionService: SessionService,
private loadingService: LoadingService
) { }
intercept(
req: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
setTimeout(() => {
if (showLoading) {
this.loadingService.show();
}
}, 500);
let showLoading = true;
if (this.sessionService.headers.length > 0) {
for (const x of this.sessionService.headers) {
req = req.clone({
headers: req.headers.set(x.key, x.value)
});
}
}
return next.handle(req)
.do(
(response) => {
if (response instanceof HttpResponse) {
showLoading = false;
this.loadingService.hide();
}
},
(error) => {
showLoading = false;
this.loadingService.hide();
});
}
}
答案 0 :(得分:11)
刚遇到同样的问题。即使http请求被取消, finalize 运算符似乎也会触发。
public intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpSentEvent | HttpHeaderResponse | HttpProgressEvent | HttpResponse<any> | HttpUserEvent<any>> {
// request starts
return next.handle(request).pipe(
finalize(() => {
// request completes, errors, or is cancelled
})
);
}
答案 1 :(得分:0)
不确定为什么 @Davy 提供的答案尚未标记为绿色。 这是一种可行的解决方案,无需遵循可中止的获取就可以使用。
这里是工作中的demo built with Angular 8。
尝试通过网络限制(例如“慢速3G”)进行尝试,并注意到在应用程序的请求队列中至少有一个HTTP请求时,每次都会显示一个精美的动画圆圈(请参阅源代码)。
如果您仔细观察网络请求,您会发现先前的未决XHR请求在收到用户的新输入后将被取消(请注意,GitHub API对一些HTTP GET请求施加了限制,因此请使用明智地,否则您将获得403 HTTP状态代码)。 @Davy提出的方法可以很好地工作,除非您做一些花哨的操作并在有待处理的请求时按Cmd + S(在PC上为Ctrl + S)。 在这种情况下,将不会调用finalize处理程序,因为整个过程都被本机模态对话框中断。
答案 2 :(得分:0)
扩展Davy的答案,这就是我检测到中止请求的方式。
正如他所说,finalize将始终在可观察到的源完成上运行,在这种情况下,它是成功响应,错误响应或中止的请求。
我的方法的关键是跟踪您到目前为止所收到的信息。
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
let lastResponse: HttpEvent<any>;
let error: HttpErrorResponse;
return next.handle(request)
.pipe(
tap((response: HttpEvent<any>) => {
lastResponse = response;
if (response.type === HttpEventType.Response) {
console.log('success response', response);
}
}),
catchError((err: any) => {
error = err;
console.log('error response', err);
// TODO: error handling if required
return throwError(err);
}),
finalize(() => {
if (lastResponse.type === HttpEventType.Sent && !error) {
// last response type was 0, and we haven't received an error
console.log('aborted request');
}
})
);
}