摘要
Angular 7正确的方法是加载列表,然后在该列表上进行迭代以进行http调用以填充其他数据?
详细信息
我正在使用安装在Node.JS服务器上的Angular 7。
我需要显示项目列表。我可以很快获得基本细节,例如物品的名称和图片。但是,某些细节需要花费一些时间才能在后端进行计算-假设它已被购买了多少次,以及购买该物品最多的州。
想法是将基本信息加载到列表中,然后从顶部开始并开始填写复杂数据。
那我有2个API。
这是我所做的伪代码:
public ngOnInit() {
this.service.getList().subscribe(list => {
this.items = list;
list.forEach(i => pendingIds.push(i.id));
this.loadDetails();
});
}
public pendingIds = [];
public loadDetails() {
ids = this.pendingIds.popAFew();
this.service.getDetails(ids).subscribe(info => {
this.items[id].properties = info.properties;
if (pendingIds.length) {
this.loadDetails();
}
});
}
上面的代码“正常工作”,但页面抖动/在数据全部加载完毕之前响应不灵。
如果我取消loadDetails()调用,则页面将快速加载并立即响应。
我确定这个问题与可观察对象的嵌套有关,该嵌套可能执行了数百次。但是,我找不到在线示例来完成我想做的事情。
我玩过异步管道和“ rxjs / observable / from”,但我没有找到秘密的调味料。
有没有人举例说明如何延迟加载列表中的信息?
修改
我已经尝试过使用flatMap,请参见以下内容,但仍然跳动:
public pendingIds = [];
public loadDetails() {
let obs: Observable<any>;
this.pendingIds.forEach(id => {
if (!obs) {
obs = this.service.getDetails(id).pipe(tap((info) => this.loadDetails(info)));
} else {
obs = obs.pipe(
flatMap(() => this.service.getDetails(id)),
tap((infp) => this.loadDetails(info))
);
}
});
obs.subscribe(() => {{);
}
编辑2
第三种加载方式-仍然令人生畏。
let activeRequests = 0;
Observable.create((observer) => {
const interval = setInterval(() => {
if (activeRequests < 2) {
if (this.pendinIds.length > 0) {
observer.next(this.pendingIds.shift());
} else {
clearInterval(interval)
}
}
}, 25);
return () => clearInterval(interval);
})
.pipe(flatMap(id => { activeRequests++; return this.service.getDetails(id); })
.subscribe(info => { --activeRequests; this.loadDetais(info})
有什么想法吗?
答案 0 :(得分:0)
我通过使用OnPush更改检测解决了速度下降问题。
简短答案: 从叶子组件开始,然后:
changeDetection: ChangeDetectionStrategy.OnPush
添加到组件
宣言。 private ChangeDetector: ChangeDetectorRef
添加到
组件构造器。this.ChangeDetector.markForCheck();
组件中数据发生变化的任何地方。有关完整说明,请参阅:https://blog.thoughtram.io/angular/2016/02/22/angular-2-change-detection-explained.html
任何时候,使用OnPush都是一个好主意,但这会导致棘手的并发症。
例如,我的情况变得更加复杂,因为当数组元素发生更改(例如扩充数据)时,作为数组的输入属性不会触发更改检测。
我通过在父级上创建一个Subject来解决此问题,该Subject传递给列表项组件。然后,当我获得其他信息时,我调用Subject.next(已更新商品的ID)。列表项组件已订阅该主题,并且如果其ID与观察到的ID相匹配,则它将调用相同的markForCheck()调用。