javascript组件随机呈现列表需要很长时间

liwlm1x9  于 2021-09-13  发布在  Java
关注(0)|答案(2)|浏览(242)

我的一个组件出现了奇怪的行为。组件从中的服务加载对象列表 ngOInit() . 我面临的问题是完全随机的,有时需要花费大量时间来呈现此列表,有时是即时的。我已经排除了这是一个后端问题,调用后端总是很快。我发现了以下几点。加上钩子之后 DoCheck 我已经看到,当提到的问题发生时,它需要相当长的一段时间,因为 ngOnInit() 到达终点和终点 ngDoCheck() 被称为。
根据angular的文件 ngDoCheck() 被召唤 ngOnIni() 所以我不完全理解为什么有时候需要这么长时间。我补充说 console.log 每次调用的执行时间——我在调用的最后一行添加了日志 ngOnInit() ,当获取对象列表的调用实际完成时 ngDoCheck() .
这就是浏览器控制台在花费大量时间时的外观:

正如你所看到的,它已经完成了任务 ngOnInit() ,然后完成 ngDoCheck() ,完成获取项目,然后在10秒后运行 ngDoCheck() 当列表在屏幕中实际呈现时。
这是组件代码的一部分 ngOnInit()ngDoCheck() :

ngDoCheck(){
    console.log('ngDoCheck. N. Items ' + this.items.length, new Date());
  }

  ngOnInit() {
    this.isLoading = true;
    this.sensorTypeConfigEndpoint.getInheritedType().then(result => {
      this.typeInherited = result;
      if (this._markers) {
        const groups = this._markers.map(marker => marker.get('group'));
        if (groups && groups.length) {
          this.getItemsByMapVisualization(this.typeViewMap, _.cloneDeep(groups)).then( items => {
            this.items = items;
            console.log('items N. Items ' + this.items.length, new Date())
            this.isLoading = false;
          });
        }
      }
    });
    console.log('ngOnInit N. Items ' + this.items.length, new Date())
  }

这是html:

<div class="flex-cards" [ngStyle]="{'max-height': maxHeight}" [class.columnWrap]="isClusterInside" [appLoading]="isLoading">
  <div (click)="expand()" *ngIf="isClusterInside" class="grid-expand">
    <img class="filter-grey" src="assets/images/expand_cluster.svg" alt="Expand" style="width: 100%; height: 100%;margin-left: 4px">
    <p class="text-expand" style="margin-bottom: 10px">
      Expandir
    </p>
  </div>
  <section class="card" style="height: calc(100% - 12px); overflow-y: auto;">
    <div class="content-card">
      <div *ngFor="let item of items">
        {{item.text}}
      </div>
    </div>
  </section>
</div>

你知道为什么要花这么长时间才能呈现这个列表吗?这是随机发生的。

aoyhnmkz

aoyhnmkz1#

注意 ngDoCheck 在可能影响组件的更改检测周期中运行。所以它会在之后运行一次 ngOnInit 然后又被其他东西调用(也许是鼠标移动?在什么东西上盘旋?点击如果没有stackblitz复制您的问题,很难说是肯定的,但它似乎不是从您对服务的异步调用内部强制执行的。如果未触发更改检测,则不会更新dom,因此您将看不到组件。您也没有向我们展示您使用的更改检测策略,并且您在模板中使用的一些属性也会影响组件的布局,从而导致问题。
尝试使用changedetectorref手动强制检查 isLoading = false 代码的一部分。这将帮助您确定这是变更检测问题还是其他问题。如果它开始工作,我建议在官方文档中阅读更多关于变更检测和Angular 生命周期的内容,以了解如何解决这个问题——我不会比他们做得更好:)

but5z9lq

but5z9lq2#

sensorTypeConfigEndpoint 看起来像是“天使世界之外”的东西。当它对 this.itemsthis.isLoading ,angular没有意识到这一点,也没有重新绘制视图。
这就像angular在睡觉,因为它看不到任何变化。 ngDoCheck() 一种“唤醒”Angular ,并强制它考虑更改并重新绘制视图,但唤醒是一种副作用,它只允许您人工触发重新绘制。
为了正确触发重画,请使用 ngZone :

import { Injectable, NgZone } from '@angular/core';

...

constructor(public zone: NgZone) { ... }
...

this.items = items;
this.isLoading = false;
this.zone.run(() => { // The magic line
    console.log('items N. Items ' + this.items.length, new Date())
});

相关问题