我正在维护的软件不幸的是必须在 IE8 上运行。 IE8 的问题是,如果同步执行时间太长,它会抛出“脚本无响应”错误:
当 Internet Explorer 达到一段 JavaScript 同步指令的最大数量时,将显示此消息。 as described here
处理这个问题的标准方法是这样的
setTimeout(function(){ //slow code }, 1);
但是,就我而言,缓慢的部分实际上是:
jQuery(/*selectors*/).each()// iteration
如何遍历使用 jQuery().each()
找到的元素,其中实际的 .each()
部分是在超时情况下递归执行的?即使 each()
block 不执行任何操作,我仍然会收到弹出警告。大约有 20,000 个元素需要迭代...我知道...
在不重写页面上任何内容的情况下执行此操作的最佳方法是什么(假设我真的无法重写 20,000 个元素的表)。
最佳答案
仅供引用,如果您的问题实际上是由于此操作本身而发生的:
jQuery(selectors)
花费的时间太长,那么您必须将选择器更改为能够更快地评估或以某种方式更改 HTML 的选择器,以便您可以一次查询表的各个部分。 IE8 中的 jQuery 很可能使用 Sizzle 库来评估选择器,因此如果您拥有大型 HTML、选择器和 Sizzle 的组合,而这些组合对于 IE8 来说太慢,那么您将不得不更改这三者之一。
如果没有看到实际的 HTML,也可能没有某种测试平台来进行实验,我们无法帮助解决此问题的具体细节。我的猜测是,可能有一个更好的选择器,也许使用 native 支持的查询机制,例如 getElementsByTagName() 或类似的东西,但我们必须看到实际的 HTML 才能做出更具体的选择器推荐。正如您所知,在非常慢的浏览器中使用 20,000 个元素并不是一个好的开始。
如果您通过选择器查找并且只想获得迭代方面的帮助,则不能直接使用 .each()
因为它会同时运行。相反,您必须手动迭代 DOM 对象的 jQuery 列表。
function processLargeArray(items) {
// set check size to whatever number of items you can process at once
var chunk = 100;
var index = 0;
function doChunk() {
var cnt = chunk;
while (cnt-- && index < items.length) {
// process items.eq(index) here
++index;
}
if (index < items.length) {
// set Timeout for async iteration
setTimeout(doChunk, 1);
}
}
doChunk();
}
var data = jQuery(selectors);
processLargeArray(data);
仅供引用,此代码适用于来自该主题的更通用答案的 jQuery 对象:Best way to iterate over an array without blocking the UI
这是一个使用 jQuery 插件创建与 .each()
类似的接口(interface)的版本(但它是异步的)。
jQuery.fn.eachChunk = function(chunk, eachFn, completeFn) {
var index = 0;
var obj = this;
function next() {
var temp;
if (index < obj.length) {
temp = obj.slice(index, index + chunk);
temp.each(eachFn);
index += chunk;
setTimeout(next, 1);
} else {
if (completeFn) {
completeFn();
}
}
}
next();
return this;
};
jQuery(selectors).eachChunk(100, yourFn);
关于javascript - 如何递归调用 JQuery .each() 迭代,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31210261/