【发布时间】:2010-09-30 13:26:35
【问题描述】:
我的网站上有一个显示表格的网页,每 10 秒重新加载一次 XML 源数据(使用 XmlHttpRequest),然后更新表格以向用户显示数据的任何添加或删除。为此,JavaScript 函数首先清除表中的所有元素,然后为每个数据单元添加一个新行。
最近,我在 Internet Explorer 中解决了由 DOM 销毁和创建代码引起的一些内存泄漏问题(其中大部分与 JavaScript 对象和 DOM 对象之间的循环引用以及我们正在使用的 JavaScript 库有关悄悄地保持对使用new Element(...) 创建的每个 JS 对象的引用,直到页面被卸载)。
解决了内存问题后,我们现在发现了一个基于 CPU 的问题:当用户有大量数据要查看时(100+ 个数据单元,这等于要创建 100 个<tr> 节点,加上所有每列的表格单元格),该进程占用 CPU,直到 Internet Explorer 提示用户:
停止运行此脚本?
此页面上的脚本导致 Internet Explorer 运行缓慢。 如果它继续运行,您的计算机可能会变成 没有反应。
似乎运行行和单元格创建代码乘以 100 多条数据是导致 CPU 使用率飙升的原因,该函数运行时间“太长”(从 IE 的角度来看),从而导致IE 为用户生成此警告。我还注意到,虽然“更新屏幕”功能针对 100 行运行,但 IE 不会重新呈现表格内容,直到该功能完成(因为 JS 解释器在该时间段内使用 100% CPU,我假设) .
所以我的问题是:在 JavaScript 中有没有办法告诉浏览器暂停 JS 执行并重新渲染 DOM?如果没有,是否有任何策略来处理创建大量 DOM 节点并且 不 让浏览器阻塞?
我能想到的一种方法是异步处理“更新表”逻辑;也就是说,一旦完成重新加载 XML 数据的 Ajax 方法,将数据放入某种数组中,然后设置一个函数(使用setInterval())运行,该函数一次处理一个数组元素。然而,这似乎有点像在 JavaScript 环境中重新创建线程,这似乎会变得非常复杂(即,如果在我仍在重新创建表的 DOM 节点时触发另一个 Ajax 数据请求怎么办?等等)
更新:只是想解释一下我为什么接受 RoBurg 的回答。在进行一些测试时,我发现我的框架中的new Element() 方法(我正在使用mootools)比IE7 中的传统document.createElement() 慢大约2 倍。我跑了一个测试,创建1000个<spans>并将它们添加到<div>,在IE7上使用new Element()大约需要1800ms(在Virtual PC上运行),传统方法大约需要800ms。
我的测试还揭示了一种更快的方法,至少对于像我这样的简单测试:使用DocumentFragments as described by John Resig。使用 IE7 在同一台机器上运行相同的测试需要 247 毫秒,比我原来的方法提高了 9 倍!
【问题讨论】:
标签: javascript ajax dom