如何阻止激烈的 Javascript 循环冻结浏览器

IT技术 javascript jquery performance loops
2021-02-10 01:03:28

我正在使用 Javascript 来解析一个包含大约 3,500 个元素的 XML 文件。我使用的是 jQuery“each”函数,但我可以使用任何形式的循环。
问题是浏览器在循环执行时冻结了几秒钟。在不使代码减慢太多的情况下停止冻结浏览器的最佳方法是什么?

$(xmlDoc).find("Object").each(function() {
    //Processing here
});
6个回答

我会放弃“each”函数,转而使用 for 循环,因为它更快。我还会使用“setTimeout”添加一些等待,但仅在需要时才这样做。您不想每次都等待 5 毫秒,因为处理 3500 条记录大约需要 17.5 秒。

下面是一个使用 for 循环的示例,该循环以 5 毫秒的间隔处理 100 条记录(您可以对其进行调整),这会产生 175 毫秒的开销。

var xmlElements = $(xmlDoc).find('Object');
var length = xmlElements.length;
var index = 0;
var process = function() {
  for (; index < length; index++) {
    var toProcess = xmlElements[index];
    // Perform xml processing
    if (index + 1 < length && index % 100 == 0) {
        setTimeout(process, 5);
    }
  }
};
process();

我还将对 xml 处理的不同部分进行基准测试,以查看是否存在可以修复的瓶颈。您可以使用 firebug 的分析器在 firefox 中进行基准测试,并像这样写到控制台:

// start benchmark
var t = new Date();
// some xml processing
console.log("Time to process: " + new Date() - t + "ms");

希望这可以帮助。

很酷的代码。也许我遗漏了一些东西,但我必须在 setTimeout() 之后添加 aindex++和 abreak才能使其正常工作。
2021-03-14 01:03:28
这是一个好主意 - 定期使用 setTimeout。它在超时为 0 的情况下工作。
2021-03-17 01:03:28
我不知道我是否遗漏了什么,但是根据您在此处提供的内容进行模制时,我的代码将进入无限循环。
2021-03-25 01:03:28
我已经为几个需要在客户端进行大量数据处理的 Web 应用程序做到了这一点。即使它确实需要一些重组,它也像魅力一样工作。
2021-03-30 01:03:28
更好地使用 console.time() 和 console.timeEnd() 进行基准测试
2021-04-13 01:03:28

在处理之间设置超时以防止循环周期吃掉所有浏览器资源。总的来说,处理和循环所有内容只需要几秒钟,对于 3,500 个元素来说并非不合理。

var xmlElements = $(xmlDoc).find('Object');

var processing = function() {
  var element = xmlElements.shift();

  //process element;

  if (xmlElements.length > 0) {
    setTimeout(processing, 5);
  }
}

processing();
我决定采用这种方法,但我只每 50 个元素运行一次 setTimeout。是的,它的超时时间为 0。
2021-03-18 01:03:28
@Christoph - 您不需要传递任何超时间隔 '0',因为默认值为0.
2021-04-08 01:03:28

我会考虑将 3500 个元素从 xml 转换为 JSON 服务器端,或者甚至更好地将其上传到转换后的服务器,以便它从一开始就对 JS 来说是原生的。

这将最大限度地减少您的负载,并使文件大小也变得更小。

您可以 setTimeout() 的持续时间为零,它将根据需要产生

使用 Turboid 框架可以在不冻结浏览器的情况下进行长循环。有了它,您可以编写如下代码:

loop(function(){  
        // Do something...  
}, number_of_iterations, number_of_milliseconds);

这篇 turboid.net 文章中的更多详细信息:Javascript 中的真实循环