javascript - 如何递归调用 JQuery .each() 迭代

标签 javascript jquery performance internet-explorer internet-explorer-8

我正在维护的软件不幸的是必须在 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/

相关文章:

mysql - 选择 order By 并限制 3,000,000 行表的慢速

python - 加快简单距离计算速度

javascript - 如果未选择单选按钮,则禁用 "Browse"按钮

javascript - 当鼠标移出时如何隐藏元素

javascript - 如何仅将选定列表中的 1 个值发布到 Controller 代码

javascript - 使用带有 CodeIgniter 的 AJAX 上传文件

javascript - 弹出窗口 react 不够灵敏

php - 在不刷新 PHP 页面的情况下提醒用户

javascript - 将字符串数组转换为数字

mysql - 数据库太大 - 存储为行或序列化数据?