Angular 7-分块加载数据会降低页面速度

时间:2018-12-05 23:13:41

标签: angular angular7

摘要

Angular 7正确的方法是加载列表,然后在该列表上进行迭代以进行http调用以填充其他数据?

详细信息

我正在使用安装在Node.JS服务器上的Angular 7。

我需要显示项目列表。我可以很快获得基本细节,例如物品的名称和图片。但是,某些细节需要花费一些时间才能在后端进行计算-假设它已被购买了多少次,以及购买该物品最多的州。

想法是将基本信息加载到列表中,然后从顶部开始并开始填写复杂数据。

那我有2个API。

  1. 返回包含其名称,价格和图片的200多种商品的清单(以500毫秒为单位)。
  2. 给出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})

有什么想法吗?

1 个答案:

答案 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()调用。