我正在开发一个现有的 Angular 应用程序。版本是 Angular 4。
应用程序从许多不同的组件对 REST API 进行 HTTP 调用。
我想为每个 HTTP 请求显示一个自定义微调器。由于这是一个现有的应用程序,因此有很多地方可以调用 REST API。而且处处改代码也不是一个可行的选择。
我想实现一个抽象的解决方案来解决这个问题。
如果有任何选择,请提出建议。
最佳答案
@jornare 在他的解决方案中有一个好主意。他正在处理多个请求的案例。然而,代码可以写得更简单,无需创建新的可观察对象并将请求存储在内存中。下面的代码还使用了 RxJS 6 和管道运算符:
import { Injectable } from '@angular/core';
import {
HttpRequest,
HttpHandler,
HttpInterceptor,
HttpResponse
} from '@angular/common/http';
import { finalize } from 'rxjs/operators';
import { LoadingService } from '@app/services/loading.service';
import { of } from 'rxjs';
@Injectable()
export class LoadingInterceptor implements HttpInterceptor {
private totalRequests = 0;
constructor(private loadingService: LoadingService) { }
intercept(request: HttpRequest<any>, next: HttpHandler) {
this.totalRequests++;
this.loadingService.setLoading(true);
return next.handle(request).pipe(
finalize(() => {
this.totalRequests--;
if (this.totalRequests === 0) {
this.loadingService.setLoading(false);
}
})
);
}
}
将此拦截器服务添加到您的模块提供程序中:
@NgModule({
// ...
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: LoadingInterceptor, multi: true }
]
})
export class AppModule { }
下面是一个LoadingService
实现的例子:
@Injectable()
export class LoadingService {
private isLoading$$ = new BehaviorSubject<boolean>(false);
isLoading$ = this.isLoading$$.asObservable();
setLoading(isLoading: boolean) {
this.isLoading$$.next(isLoading);
}
}
下面是如何在组件中使用 LoadingService
:
@Component({
selector: 'app-root',
template: `
<ng-container *ngIf="loadingService.isLoading$ | async">
<i class="loading"></i>
</ng-container>
<router-outlet></router-outlet>
`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class AppComponent {
constructor(public loadingService: LoadingService) {}
}
关于每个 HTTP 请求的 Angular 显示微调器,代码更改非常少,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49385369/