Angular 7: принятие мер, если запрос занимает слишком много времени - PullRequest
1 голос
/ 07 марта 2019

Итак, у меня есть значок загрузки, который отображается, когда приложение взаимодействует с сервером. Когда запрос выходит, отображается значок, а когда ответ возвращается, удалите значок. Это довольно просто.

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    this.spinnerService.addPendingLoad();

    //We need to add this header to all outbound requests to note this is an XHR request
    const authReq = req.clone({
      headers: req.headers.set("X-Requested-With", "XMLHttpRequest")
    });

    return next.handle(authReq).pipe(
      tap((event: HttpEvent<any>) => {
        if(event instanceof HttpResponse) {
          this.spinnerService.removePendingLoad();
        }
      }));
  }

export class SpinnerService {
  pendingLoads: number = 0;

  constructor(private spinnerService: NgxSpinnerService) {}

  addPendingLoad() {
    this.pendingLoads++;
    this.spinnerService.show();
  }

  removePendingLoad() {
    this.pendingLoads--;
    if(this.pendingLoads <= 0) {
      this.spinnerService.hide();
    }
  }
}

Итак, проблема, которую я хочу решить, заключается в том, что большую часть времени запросы будут возвращаться немедленно, поэтому в конечном итоге вы получаете очень быстрое отображение / скрытие значка, и это может быть довольно неприятным опытом.

Я попытался установить тайм-аут на this.spinnerService.hide();, возможно, 500 мс, поэтому значок загрузки всегда будет отображаться на экране минимальное количество времени. Это более приятное занятие, но оно приводит к тому, что значок загрузки отображается дольше, чем он есть на самом деле, что может заставить приложение «чувствовать» вяло.

То, к чему я стремлюсь, - это возможность как-то измерить, сколько времени ожидал запрос, и отображать значок загрузки только в том случае, если запрос занимает ненормально длительное время.

Так, например, большинство запросов будут отвечать в течение 100 мс или около того. Если что-то случится, что приведет к задержке ответа, то значок загрузки будет отображаться только после этого маркера 100 мс. Таким образом, если полный запрос занял 300 мс, значок загрузки будет отображаться только от 100 мс -> 300 мс. Если запрос занимает менее 100 мс, значок не должен отображаться.

Возможно ли что-то подобное? Я понимаю, что крайние случаи будут происходить, как запрос, принимающий 105 мс, так что я все равно столкнусь с этим дребезгом, но IMO - это компромисс с постоянным отображением значка загрузки на экране, даже если он не нужен.

1 Ответ

2 голосов
/ 07 марта 2019

Вместо отображения счетчика сразу, вы можете отобразить его в обратном вызове setTimeout:

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

  let delayExpired = false;

  const timeout = setTimeout(() => {                   // Set spinner timeout
    delayExpired = true;
    this.spinnerService.addPendingLoad();              // Show spinner after delay
  }, 100);                                             // Wait 100 ms to show spinner

  ...

  return next.handle(authReq).pipe(
    tap((event: HttpEvent<any>) => {
      if (event instanceof HttpResponse) {
        clearTimeout(timeout);                         // Cancel spinner timeout
        if (delayExpired) {
          this.spinnerService.removePendingLoad();     // Hide spinner
        }
      }
    }));
  }
}

См. этот стек для демонстрации.

...