angular - 在 Angular 6 应用程序中多次发送 Http 请求
问题描述
在我们的 Angular 6 应用程序中,我注意到一些 Http GET 调用至少执行了两次。有时 OPTIONS 和/或第一个 GET 被取消,只有第二个调用成功。在其他情况下,相同的 GET 调用会执行两次或更多次。
页脚组件调用服务来获取当前应用程序版本并将其显示为模板。一个简单的订阅 Observable,没有任何特殊的操作符。
更新
经过进一步调查,问题似乎出combineLatest
在 HttpInterceptor 中。由于 BehaviourSubject (每个)将两个 observables 作为 observables 发出,我猜想这些 Subjects 发出的不同速度/时间,使得 combineLates 被触发两次或更多。
模拟服务(从 BehaviourSubject 发出 observables)
export class ImpersonatorService {
public get changeHandler(): Observable<string> {
return this.changeHandlerInternal.asObservable();
}
private changeHandlerInternal = new BehaviorSubject<string>(this.get());
private key = "impersonate";
constructor(private cookieService: CookieService) {}
public set(impersonate: string) {
this.cookieService.put(this.key, impersonate);
this.changeHandlerInternal.next(impersonate);
}
private get(): string {
let impersonate = this.cookieService.get(this.key);
if (impersonate === undefined || impersonate === null || impersonate === "") {
impersonate = "";
}
return impersonate;
}
}
页脚组件:
export class FooterComponent implements OnInit {
public applicationInfo: Observable<ApplicationInfo>;
constructor(private applicationService: ApplicationInfoService) {}
ngOnInit() {
this.applicationInfo = applicationService.getApplicationInfo();
}
}
页脚模板
<div>
{{ (applicationInfo | async)?.version }}
</div>
应用服务
export class ApplicationInfoService {
constructor(private http: HttpClient, @Inject(APP_CONFIG) private config: IAppConfig) {}
public getApplicationInfo(): Observable<ApplicationInfo> {
return this.http.get<ApplicationInfo>(this.config.apiEndpoint + "/api/applicationinfo");
}
}
仅从页脚组件调用应用程序服务。
我们还使用 HttpInterceptor 来注入标头:
export class HttpInterceptor implements HttpInterceptor {
constructor(private impersonator: ImpersonatorService, private profileService: ProfileService, private languageService: TranslateService) {}
public intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return this.impersonator.changeHandler
.combineLatest(this.profileService.changeHandler, (user, profile) => {
let customHeaders = req.headers.set("X-Impersonate", user).set("X-Profile", profile);
if (customHeaders.has("Content-Type")) {
if (customHeaders.get("Content-Type") === "multipart/form-data") {
customHeaders = customHeaders.delete("Content-Type");
}
} else {
customHeaders = customHeaders.set("Content-Type", "application/json");
}
const clonedReq = req.clone({ headers: customHeaders, withCredentials: true });
return next.handle(clonedReq);
})
.switch();
}
}
从其他 SO 响应中读取,这似乎与种族问题有关。然而,发现的其他案例是使用 switchMap 或其他运算符在这些场景中导致问题。
通过调试,我可以看到在 HttpInterceptor 内部有两个对 ApplicationInfo 端点的请求到达。但是我怎样才能确保没有重复的请求被发送呢?
解决方案
推荐阅读
- angular - Angular 无法读取未定义错误的属性订阅
- linux - Arm EL0 地址转换
- android - java.lang.NoSuchMethodException:deaeb
[接口cpi,类android.content.Context] - angular - 我希望我的 Angular 检查两个链接(基本路径)而不是一个链接,以保证离子角度的路径
- progressive-web-apps - Workbox Service Worker - 忽略外部 URL 进行缓存?
- python - 如何在 Azure Data Studio 中显示 IPython Notebook Output (Pandas Data Frame) 的所有列?
- raspberry-pi - 如何使用 Raspberry Pi 编写 SD/mmc 程序
- web-component - connectedCallback 中的自定义 Web 组件设置属性
- rust - 在 Rust 中使用 iodbc
- python - 如何在光栅图像中绘制轮廓或形状的偏移量?