【发布时间】:2019-05-07 14:36:21
【问题描述】:
总结
什么是正确的 Angular 7 加载列表的方法,然后遍历该列表进行 http 调用以填写其他数据?
详情
我在 Node.JS 服务器上使用 Angular 7。
我需要显示一个项目列表。我可以非常快速地获得基本细节,说出物品的名称和图片。但是,有些细节需要一段时间才能在后端进行计算 - 比如说它被购买的次数和购买最多商品的状态。
思路是在列表中加载基本信息,然后从顶部开始,开始填写复杂数据。
所以我有 2 个 API。
- 返回包含 200 多件商品及其名称、价格和图片的列表(响应时间约为 500 毫秒)。
- 给定一个 id 列表,返回项目的复杂信息(~250ms-2,000ms)。
这是我所做的伪代码:
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})
有什么想法吗?
【问题讨论】: