在拦截器中完成时如何等待响应
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();
}
}
}
我 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();
}
}
}