我有一个Angular父组件,它控制一个对象列表,即spacecrafts
。对象数组被加载到父组件中,我将其称为list
,我的子组件,或cards
,每个组件都接收该对象的一个示例以显示其信息。我使用*NgFor
,调用组件选择器,并通过@Input
传入spacecraft
。
注意:有两个不同的组件使用这种逻辑,一个是以“列表视图”显示我们的航天器,另一个是允许我们显示“网格视图”-类似于桌面文件夹。有一个UI开关来确定执行哪个*ngFor
循环- list或grid。它们使用父组件list
中的相同spacecraft
列表,并根据需要在每个子组件中获取少量附加信息。
当我的spacecraft
列表被返回时,它们包含对象/数组,其中一个数组是航天器的Tasks[]
。这些Spacecraft被小心地加载到后端(C#)中,每个嵌套实体不一定有所有级别的.Include()
来带回FULL对象,因为每个Task
都有自己的实体/集合,这些实体/集合不需要这些组件。
在我们的Task
实体中,我们有一个Event
的集合。(因此,Spacecrafts
有一个包含Events
的Tasks
的集合。)我们在Spacecraft
上没有单独的后端模型属性Events[]
。当我们为这个组件提取Spacecraft查询时,我们不包括Events
,它将嵌套在每个Spacecraft的Tasks
中。这样做真的会对速度产生影响,而且我们以前还没有需要自己访问航天器的事件。我们有单独的服务来获取航天器的Tasks[]
,然后我们将其包含在Events[]
中。
最近,我们有一个任务,要显示列表组件中spacecraft
的所有Tasks
之间存在的所有Events
的COUNT,分为3个类别的Severity
。我们有一个单独的http方法,它允许我们从数据库中获取所有Event
,其属性spacecraftId
与给定spacecraft
的id匹配,而不必在LINQ查询中深入3层,返回不需要的信息并浏览航天器的任务。这在应用程序的每个其他领域都能完美工作。
我目前正在做的是将我的航天器列表加载到我的list
组件中,然后使用一个循环进行单独的调用以获得每个航天器的Events[]
,并将每个响应Map到航天器模型的FRONT END only属性'Events[]'(我为此任务添加的)。
一旦通过Input()接收到Events[]数据,就可以在子组件中加载它,但是,当视图在两种视图类型之间翻转时,执行相同的调用来获取每个航天器的Events[]远不是理想的,因为它只是一吨的数据。
理想情况下,我希望将spacecraft[]
加载到父组件中,这样我就可以重用相同的数据,而不会有无休止的http调用。我希望这是有意义的。我现在的代码如下,它使用了async/await,它确实工作了。我必须实现async/await,因为子组件在Events[]
被返回到它们的spacecraft
之前就已经加载了,而且一旦http调用完成,航天器就不会更新。(我也试过设置一个布尔值,在Events[]的最后一次迭代完成时翻转-不起作用!)
列出组件:
公共航天器:int [];
ngOnInit(): void {
getSpacecraft()
}
getSpacecraft() {
this.spacecraftService.getSpacecrafts(filters).subscribe(async res => {
this.spacecrafts = res;
await this.getSpacecraftEvents();
});
public async getSpacecraftEvents() {
for (let sp of this.spacecrafts) {
await this.spacecraftService.getEventsBySpacecraftAsync(sp.id).then(
res => {
sp.Events = [...res];
}
)
};
this.isLoading = false;
}
服务方式:
getEventsBySpacecraftAsync(spacecraftId: string): any {
let params = {
withDetails: false
};
return this.http.get<any>(`${this.endpoint}/${spacecraftId}/Events`, { params: params }).toPromise();
}
我不一定喜欢这样,因为控制视图的组件需要等待另一个组件代表它们同步解析数据。我真的在尝试利用任何RxJs功能,以便在组件中接触数据之前将这些额外的Event
调用完全提取到服务层中,但我不确定该如何处理它。有没有更好的办法?(当然,即使不是RxJs)。我不能使用解析器-这是我尝试的另一种方法。
而且,是的,我100%考虑采用一个新的后端流程,让航天器的Events[]在初始的http调用中到达,但我真的很想看看除了async/await之外是否还有其他选项。
2条答案
按热度按时间vdzxcuhz1#
我可以想到两种方法来做到这一点:您可以创建一个中间组件,用于加载事件数据并在网格和列表组件之间切换,而无需在每次切换视图时调用服务器,或者,您可以使用map迭代所有航天器并将事件数据附加到它们,例如:
根据您对RxJS的了解程度,第二种方法有更有效的方法,但这说明了这一点。
9ceoxa922#
首先,如果没有必要,我建议你不要把承诺和可观察到的东西混在一起。如果可以的话,最好还是用Angular 来观察。因此,我将从getEventsBySpacecraftAsync中删除async,并使其返回observable:
现在在getSpacecraftEvents中,您实际上是在一个接一个地调用许多事件。等待for循环中的每个调用。相反,您可以同时进行这些调用,这将大大加快此过程。此外,由于我们在服务中切换到可观测数据,我们在这里也这样做:
代替for循环,我们将航天器数组Map到可观测量数组,并使用forkJoin将它们连接在一起。订阅后,他们同时被要求。
它仍然不是完美的,因为它不是在你获取航天器后等待,而是在单独的订阅中完成的。因此,让我们进一步修复它,我们将使它成为一个返回observable但不订阅它的方法,稍后我们将在getSpacecraft()中使用它。
getSpacecraft方法:
现在使用switchMap,我们将两个系列的调用加入到一个可观察对象中,该对象在一个订阅中执行。和事件调用将同时执行。