【问题标题】:Angular 5 / HttpInterceptor / Detect (cancelled) xhrAngular 5 / HttpInterceptor / 检测(取消)xhr
【发布时间】:2018-10-14 18:31:28
【问题描述】:

在我的 Angular 应用程序中,我看到 chrome(取消)api 调用启动得太快了。如果请求未完成,我还有一个 HttpInterceptor 会在 500 毫秒后触发每个 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();
          }
        );
    }
  }

【问题讨论】:

  • 你找到办法了吗?
  • 将处理程序响应包装在另一个 Observable 中,如 here 所述,似乎工作得很好

标签: angular httpclient angular-http-interceptors


【解决方案1】:

刚刚遇到同样的问题。 finalize 操作符似乎即使在 http 请求被取消时也会触发。

    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】:

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

【讨论】:

  • 不错的一个!在与 OP 类似的场景中使用(Http 流量状态指示器,当请求被取消时,必须返回空闲特别困难,故意/设计)。 ??
【解决方案3】:

不知道为什么 @Davy 提供的答案还没有被标记为绿色勾号。 这是一个可行的解决方案,可以在不遵守可中止提取的情况下使用。

这是一个有效的demo built with Angular 8

尝试使用网络限制(例如,“Slow 3G”)并注意每次应用程序的请求队列中至少有一个 HTTP 请求时都会显示精美的动画圆圈(请参阅源代码)。

如果您仔细观察网络请求,您会发现之前的未决 XHR 请求将在收到用户的新输入后被取消(请注意,GitHub API 对 HTTP GET 请求的数量施加了限制,因此请使用明智地,否则您将返回 403 HTTP 状态代码)。 @Davy 提出的方法可以正常工作,除非你做一些花哨的事情并在有待处理请求时按 Cmd+S(PC 上的 Ctrl+S)。 在这种情况下,将不会调用 finalize 处理程序,因为整个过程被本机模式对话框中断。

【讨论】:

  • 接受答案:人们似乎不再这样做了;)
猜你喜欢
  • 2018-05-14
  • 2021-04-09
  • 2018-12-02
  • 2018-05-16
  • 2018-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多