【问题标题】:Angular 7 - Loading data in chunks slows down the pageAngular 7 - 分块加载数据会减慢页面速度
【发布时间】:2019-05-07 14:36:21
【问题描述】:

总结

什么是正确的 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})

有什么想法吗?

【问题讨论】:

    标签: angular angular7


    【解决方案1】:

    我通过使用 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.next(更新项目的 ID)。列表项组件订阅了主题,如果其 id 与观察到的 id 匹配,则它调用相同的 markForCheck() 调用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-02
      • 2021-05-13
      • 1970-01-01
      • 1970-01-01
      • 2020-12-07
      相关资源
      最近更新 更多