在拦截器中完成时如何等待响应

How to wait for the response when is finished in interceptor

我 interceptor.I 想显示加载微调器,所以在任何我有订阅方法等待订阅完成的地方,在那个时候显示加载微调器,当它完成时隐藏它加载微调器。

如果我在每个组件中都这样做,那很容易,而且很有效。

ngOnInit() {
    this.spinnerService.show();
    this.service.methodName().subscribe(data => {
    },error => {
    },() => {
        this.spinnerService.hide();
    })
}

但是我如何在这个拦截器中做到这一点?使用此代码,仅在发出请求时微调器显示的时间非常短,然后 disapperas.I 有需要更长时间的请求...

 if (request.url.includes(this.apiUrl)) {
    this.spinnerService.show();
    let headers = new HttpHeaders();
    headers = headers.append('Content-Type', 'application/json');
    headers = headers.append('Authorization', `Bearer ${token}`);
    cloneRequest = request.clone({ headers: headers });
} else {
    cloneRequest = request.clone();
}
return next.handle(cloneRequest).pipe(map(response => {
            this.spinnerService.hide();
            return response;
        })).pipe(catchError(error => {
            let errorMessage = 'An unexpected error occured';
            if (error.error && error.error.message) {
                errorMessage = error.error.message;
            }
            // TODO: Error notifications are currently disabled.
            if (request.url.includes('login')) {
                this.notificationService.showError(errorMessage);
            }
            return throwError(error)
        }));

问题是您有多个 API 请求,因此当第一个请求完成时,它会隐藏微调器,即使第二个请求尚未完成。您可以在 spinnerService:

上使用计数器
@Injectable({
  providedIn: 'root'
})
export class SpinnerService {
  get shouldShow(): boolean {
    return !!this.count;
  }

  private count: number = 0; 

  show(): void {
    this.count++;
  }

  hide(): void {
    this.count = Math.max(0, this.count - 1);
  }
}

您必须更新拦截器才能处理此问题,因为 api 不显示微调器的调用现在会减少微调器计数。要对此进行调整,您应该检查它是否应该减少。此外,rxjs 的 finalize 管道是放置此类内容的完美位置:

const showSpinner = request.url.includes(this.apiUrl);

if (showSpinner) {
  this.spinnerService.show();

  cloneRequest = request.clone({ headers: new HttpHeaders({
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${token}`
  }) });
} else {
  cloneRequest = request.clone();
}

return next.handle(cloneRequest).pipe(
  catchError(error => //...),
  finalize(() => {
    if (showSpinner) {
      this.spinnerService.hide();
    }
  })
);

Ng4LoadingSpinnerService 的包装器服务看起来像这样简单:

@Injectable({
  providedIn: 'root'
})
export class SpinnerService {
  private count: number = 0; 

  constructor(private ss: Ng4LoadingSpinnerService) {}

  show(): void {
    if (!this.count) {
      this.ss.show();
    }

    this.count++;
  }

  hide(): void {
    this.count = Math.max(0, this.count - 1);

    if (!this.count) {
      this.ss.hide();
    }
  }
}