【问题标题】:Angular2 setinterval blocked while dom changesdom更改时Angular2 setinterval被阻止
【发布时间】:2018-06-18 13:39:39
【问题描述】:

我有一个基本的 Javascript/JQuery 应用程序,我现在正在迁移到 Angular2,我的 UI 使用 material.angular.io。

在旧版本中,当我使用“setInterval(func,200);”时每 200 毫秒查询一次服务器,每 200 毫秒调用一次,即使在使用 JQuery 的 append(content) 或 html(content) 函数添加 DOM 元素时也是如此。

现在在 Angular2 中,虽然 DOM 使用 *ngFor 进行了更改并且更改很大(从服务器获取约 200 行并将它们显示为带有诸如切换按钮之类的 Material 组件的表格行),但一切都冻结了大约 1 秒钟。服务器的日志向我显示,呼叫确实停止了大约 1 秒钟,然后每 200 毫秒再次恢复。 但是当我以较小的组添加 DOM 元素(即:每 200 毫秒 10 个项目)时,一切都很好。

当我使用 F11 切换全屏时,当浏览器重绘布局以匹配新窗口大小时,也会发生这种情况。

使用 Chrome 的调试控制台,我可以看到“Timer Fired(zone.js:2087)”显示“Recurring handler takes 731.18 ms”警告。我不确定问题是因为我的代码还是因为它是一个 material.io 问题,但我认为 Angular 的 setInterval 与普通的 JavaScript setInterval 不同?

以下是相关代码:

<tbody>
  <tr *ngFor="let io of inputs; trackBy: trackByFn">
    <td>{{io.id}}</td>
    <td>{{io.name}}</td>
    <td>{{io.description}}</td>
    <td><mat-slide-toggle>Test</mat-slide-toggle></td>
    <td>{{io.device}}</td>
  </tr>
</tbody>

来自服务器的日志显示上次查询的时间:

15:40:25.229 stat.service.ts:108 200
15:40:25.430 stat.service.ts:108 201
15:40:25.630 stat.service.ts:108 201
15:40:25.831 stat.service.ts:108 201
15:40:26.031 stat.service.ts:108 200
15:40:26.235 stat.service.ts:108 203
15:40:26.435 stat.service.ts:108 201
15:40:26.636 stat.service.ts:108 201
15:40:26.838 stat.service.ts:108 202
15:40:27.039 stat.service.ts:108 201
15:40:27.895 stat.service.ts:108 856 // WHEN THE COMPONENT LOADS
15:40:28.200 stat.service.ts:108 305
15:40:28.442 stat.service.ts:108 242
15:40:28.679 stat.service.ts:108 237
15:40:28.901 stat.service.ts:108 221
15:40:29.131 stat.service.ts:108 231
15:40:29.363 stat.service.ts:108 231

【问题讨论】:

  • 每 200 毫秒调用一次 - 这不太可能。如果主线程被阻塞,则它被阻塞。该案例并非特定于 Angular(它没有自己的 setInterval,只有 Zone.js 修补的那个),而是针对任何阻塞的 JS 代码。尝试 setInterval 和 for 大循环,你会看到。

标签: javascript angular performance dom setinterval


【解决方案1】:

也许这是 Angular 中 ChangeDetection 的问题。当您更改对象时,它会重新渲染整个事物。尝试在您的组件中实现 ChangeDetectionStrategy 并查看是否有任何改进。您的组件代码将如下所示:

@Component({
  selector: "your-comp",
  templateUrl: "./your.component.html",
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class YourComponent{
  constructor(private cdr: ChangeDetectorRef) {}

 // this.cdr.markForCheck(); use code for change on DOM when you get data in observable
}

希望对你有帮助

【讨论】:

  • 没有。正如我所说,当我单击 F11 切换全屏时也会发生这种情况,并且仅在修改 DOM 时才会发生。当设置了 DOM 并且只有数据更改时,绑定可以正常工作,没有任何问题。只是最初的 DOM 修改需要时间。
  • 200 行数据并不多,我渲染了大约 10000 行具有 7 个属性的数据,但从未发现任何问题。你应该深入研究它来解决这个问题。可能这在未来会让人头疼。
猜你喜欢
  • 1970-01-01
  • 2018-05-20
  • 2017-01-04
  • 1970-01-01
  • 2011-06-09
  • 1970-01-01
  • 2020-06-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多