可以在没有浏览器阻塞的情况下添加大量DOM节点吗?

时间:2009-01-09 18:32:49

标签: javascript ajax dom

我的网站上有一个显示表格的网页,每隔10秒重新加载XML源数据(使用XmlHttpRequest),然后更新表格以向用户显示数据的任何添加或删除。为此,JavaScript函数首先清除表中的所有元素,然后为每个数据单元添加一个新行。

最近,我通过这个DOM破坏和创建代码导致了Internet Explorer中的大量内存泄漏(大多数代码都与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>,使用new Element()在IE7上运行大约1800毫秒(在Virtual PC上运行),传统方法大约需要800毫秒。

我的测试还揭示了一种更快的方法,至少对于像我这样的简单测试:使用DocumentFragments as described by John Resig。使用IE7在同一台计算机上运行相同的测试需要247毫秒,与原始方法相比有了 9x 的改进!

5 个答案:

答案 0 :(得分:6)

100 <tr>并不是那么多......你还在使用那个框架new Element()吗?这可能是它的原因。

您应该测试new Element() vs document.createElement() vs .innerHTML的速度

还尝试在内存中构建dom树,然后在最后将其附加到文档中。

最后注意你不是经常看到.length,或者是那样的其他比特和鲍勃。

答案 1 :(得分:1)

我在第3000轮表行的复杂数据中遇到过类似的问题,所以你的代码有些不完全正确。它是如何在Firefox中运行的?你可以在几种不同的浏览器中查看。

你是否在任何地方绑定onPropertyChange?这是一个非常危险的事件,它早先引起了严重的特定头痛。你在任何地方使用CSS选择器吗?这些都是出了名的慢。

答案 2 :(得分:1)

您可以创建一个字符串表示形式并将其添加为节点的innerHTML

答案 3 :(得分:0)

你可以cloneNode(false)要重复的元素,然后将其用于循环,而不是每次都生成元素。

答案 4 :(得分:0)

避免使用一个大的for循环来渲染所有数据。看看将数据拆分成更小的块。

使用while循环渲染每个较小的块。完成该块后,使用setTimeout [time 1ms]调用下一个块,为浏览器提供“喘息机会”。

您可以避免同时使用while循环,只需使用setTimeout。

使用setTimeout技术会稍微降低执行速度,但是你不应该收到警告信息。

要考虑的另一件事是不要将每个元素单独附加到文档中。查看创建一个新的tbody,将新行附加到新的tbody,并将tbody附加到表中。

还有很多其他因素会导致应用程序变慢。将它们全部清除可能很有趣。

这里有一个关于警告的简洁研究:http://ajaxian.com/archives/what-causes-the-long-running-script-warning

相关问题