Angular 5 / HttpInterceptor / Detect (cancelled) xhr

↘锁芯ラ 提交于 2019-12-10 12:49:24

问题


In my angular app I'm seeing chrome (cancel) api calls that fire off too rapidly. I also have an HttpInterceptor that triggers a loading indicator with every HttpClient request after 500ms if the request has not completed. However, on the requests that get (cancelled) there does not seem to be any new event to subsequently hide my loading indicator.

Is there a way to detect 'cancelled' requests in the HttpInterceptor so I can hide my loading indicator again?

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();
    });
}
}

回答1:


Just encountered the same problem. The finalize operator seems to trigger even when the http request is cancelled.

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
        })
    );
}



回答2:


Not sure why the answer provided by @Davy hasn't been marked with a green tick yet. It's a working solution that can be used without adhering to the abortable fetch.

Here is a working demo built with Angular 8.

Try it out with the network throttling (say, "Slow 3G") and notice the fancy animated circle that is being shown each and every time when there is at least one HTTP request in the application's requests queue (see more details in the source code).

If you look closely to the network requests you'll see that the previous pending XHR requests will have been canceled upon receiving a new input from a user (note that GitHub API imposes a limit for a number of HTTP GET requests so use wisely, otherwise you'll have 403 HTTP status code back). The approach proposed by @Davy works fine unless you do something fancy and press Cmd+S (Ctrl+S on PC) while there is a pending request. In that case, the finalize handler won't be invoked because the whole process was interrupted by a native modal dialog.




回答3:


Expanding on Davy's answer, this is how I'm detecting an aborted request.

As he stated, finalize will always run on the observable source completing, which in this case is either a success response, an error response, or an aborted request.

The key to my approach is tracking what you have received so far.

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');
        }
      })
    );
}


来源:https://stackoverflow.com/questions/50172055/angular-5-httpinterceptor-detect-cancelled-xhr

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!