Angular 异步请求没有及时加载
Angular asynchronous request not loaded in time
我在 Angular 中尝试执行一个棘手的异步请求时遇到了一些问题。我正在显示一个用户界面,其中包含浓缩在 table 中的特定信息。 table 包含使用 HttpClient
模块提供的 http.get
方法从后端加载的 headers。我在ngOnInit()
方法中调用这个方法。偶尔会出现 table 的 headers 在显示 table 之前未加载的情况。如何避免这个问题?
实现的一些信息:
ngOnInit(): void {
this.toastService.reset();
this.load();
}
load(): void {
const workflows = this.getWorkflows();
const headers = this.getHeaders();
forkJoin([workflows, headers]).subscribe((results) => {
this.setWorkflows(results[0]);
this.setHeaders(results[1]);
}, (error) => {
console.error(`error = ${error}`);
});
}
getWorkflows(): Observable<VisibleWorkflow[]> {
return this.workflowService.getWorkflows().pipe(
map((response) => {
return this.workflows = response;
})
);
}
setWorkflows(workflows: VisibleWorkflow[]): void {
this.workflows = workflows.map((workflow) => {
return {...workflow};
});
}
getHeaders(): Observable<VisibleHeader[]> {
return this.headerService.getHeaders().pipe(
map((response) => {
return this.headers = response;
})
);
}
setHeaders(headers: VisibleHeader[]): void {
this.headers = headers;
}
感谢您的宝贵时间!
您可以使用 combineLatest
combineLatest:每当任何输入 Observable 发出一个值时,它都会使用所有输入的最新值计算一个公式,然后发出该公式的输出。 https://rxjs.dev/api/index/function/combineLatest
您遇到的问题是因为您将值分配给 this.workflows
和 this.headers
两次。首先,您在 RxJS.map
运算符内部分配一个值,然后在 forkJoin
.
的订阅中分配一个值
由于 forkJoin
仅在每个 Observable 完成后立即发出值,因此您应该仅在订阅中而不是在 RxJS.map
中分配值。
因此,您的代码如下所示:
load(): void {
const workflows = this.getWorkflows();
const headers = this.getHeaders();
forkJoin([workflows, headers]).subscribe(
// I used array deconstruction here because I prefer that over hard coded indexes
([wfs, heads]) => {
this.setWorkflows(wfs);
this.setHeaders(heads);
},
(error) => {
console.error(`error = ${error}`);
}
);
}
getWorkflows(): Observable<VisibleWorkflow[]> {
return this.workflowService.getWorkflows();
}
getHeaders(): Observable<VisibleHeader[]> {
return this.headerService.getHeaders();
}
像这样,您只是在两个请求都完成后才分配值,因此您应该不会再有时间问题了。
只要两个变量都没有设置,您也可以考虑隐藏您的 table:
<ng-container *ngIf="headers?.length && workflows">
<!-- Your table here -->
</ng-container>
如果存在时间问题,这也可以解决 ;)
我在 Angular 中尝试执行一个棘手的异步请求时遇到了一些问题。我正在显示一个用户界面,其中包含浓缩在 table 中的特定信息。 table 包含使用 HttpClient
模块提供的 http.get
方法从后端加载的 headers。我在ngOnInit()
方法中调用这个方法。偶尔会出现 table 的 headers 在显示 table 之前未加载的情况。如何避免这个问题?
实现的一些信息:
ngOnInit(): void {
this.toastService.reset();
this.load();
}
load(): void {
const workflows = this.getWorkflows();
const headers = this.getHeaders();
forkJoin([workflows, headers]).subscribe((results) => {
this.setWorkflows(results[0]);
this.setHeaders(results[1]);
}, (error) => {
console.error(`error = ${error}`);
});
}
getWorkflows(): Observable<VisibleWorkflow[]> {
return this.workflowService.getWorkflows().pipe(
map((response) => {
return this.workflows = response;
})
);
}
setWorkflows(workflows: VisibleWorkflow[]): void {
this.workflows = workflows.map((workflow) => {
return {...workflow};
});
}
getHeaders(): Observable<VisibleHeader[]> {
return this.headerService.getHeaders().pipe(
map((response) => {
return this.headers = response;
})
);
}
setHeaders(headers: VisibleHeader[]): void {
this.headers = headers;
}
感谢您的宝贵时间!
您可以使用 combineLatest
combineLatest:每当任何输入 Observable 发出一个值时,它都会使用所有输入的最新值计算一个公式,然后发出该公式的输出。 https://rxjs.dev/api/index/function/combineLatest
您遇到的问题是因为您将值分配给 this.workflows
和 this.headers
两次。首先,您在 RxJS.map
运算符内部分配一个值,然后在 forkJoin
.
由于 forkJoin
仅在每个 Observable 完成后立即发出值,因此您应该仅在订阅中而不是在 RxJS.map
中分配值。
因此,您的代码如下所示:
load(): void {
const workflows = this.getWorkflows();
const headers = this.getHeaders();
forkJoin([workflows, headers]).subscribe(
// I used array deconstruction here because I prefer that over hard coded indexes
([wfs, heads]) => {
this.setWorkflows(wfs);
this.setHeaders(heads);
},
(error) => {
console.error(`error = ${error}`);
}
);
}
getWorkflows(): Observable<VisibleWorkflow[]> {
return this.workflowService.getWorkflows();
}
getHeaders(): Observable<VisibleHeader[]> {
return this.headerService.getHeaders();
}
像这样,您只是在两个请求都完成后才分配值,因此您应该不会再有时间问题了。
只要两个变量都没有设置,您也可以考虑隐藏您的 table:
<ng-container *ngIf="headers?.length && workflows">
<!-- Your table here -->
</ng-container>
如果存在时间问题,这也可以解决 ;)