Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typo3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
防止长时间运行的javascript锁定浏览器_Javascript - Fatal编程技术网

防止长时间运行的javascript锁定浏览器

防止长时间运行的javascript锁定浏览器,javascript,Javascript,我有JavaScript,它执行大量的计算以及从DOM读取/写入值。页面很大,因此通常会在100%CPU使用率的情况下锁定浏览器长达一分钟(IE有时会更长) 有没有关于优化JavaScript以防止这种情况发生的资源(我能找到的只是如何关闭Firefox的长时间运行脚本警告)?您可以尝试在线程中执行长时间运行的计算(请参阅),尽管它们不是很好移植 您还可以尝试使用一些Javascript分析器来查找性能瓶颈。支持分析javascript。使用超时 通过将循环的内容放入单独的函数中,并以50左右的

我有JavaScript,它执行大量的计算以及从DOM读取/写入值。页面很大,因此通常会在100%CPU使用率的情况下锁定浏览器长达一分钟(IE有时会更长)


有没有关于优化JavaScript以防止这种情况发生的资源(我能找到的只是如何关闭Firefox的长时间运行脚本警告)?

您可以尝试在线程中执行长时间运行的计算(请参阅),尽管它们不是很好移植

您还可以尝试使用一些Javascript分析器来查找性能瓶颈。支持分析javascript。

使用超时

通过将循环的内容放入单独的函数中,并以50左右的超时时间从setTimeout()调用它们,javascript将获得线程控制权,并在一段时间后返回,从而允许UI查看


这是一个很好的解决方法。

如果您可以将计算算法转化为可以迭代调用的算法,您可以通过使用一个较短的超时值,以频繁的间隔将控件释放回浏览器

例如,像这样的东西

function doCalculation()
{
   //do your thing for a short time

   //figure out how complete you are
   var percent_complete=....

   return percent_complete;
}

function pump()
{
   var percent_complete=doCalculation();

   //maybe update a progress meter here!

   //carry on pumping?
   if (percent_complete<100)
   {
      setTimeout(pump, 50);
   }
}

//start the calculation
pump();
函数doccalculation()
{
//短时间做你的事
//弄清楚你有多完整
变量完成百分比=。。。。
返回完成百分比;
}
功能泵()
{
var percent_complete=doCalculation();
//也许在这里更新一个进度表!
//继续抽水?
if(percent_complete我不久前写过博客,但让我在这里为您总结一下与DOM相关的内容

  • 尽可能不频繁地更新DOM。对内存中的DOM对象进行更改,并仅向DOM追加一次
  • 使用innerHTML。在大多数浏览器中,它比DOM方法快
  • 使用事件委派而不是常规事件处理
  • 知道哪些调用是昂贵的,并避免它们。例如,在jQuery中,$(“div.className”)将比$(“#someId”)更昂贵
还有一些与JavaScript本身相关的问题:

  • 尽可能少地循环。如果一个函数收集DOM节点,另一个函数处理它们,则循环两次。相反,将匿名函数传递给收集节点的函数,并在收集节点时处理节点
  • 尽可能使用本机功能。例如,forEach迭代器
  • 使用setTimeout让浏览器偶尔呼吸一次
  • 对于具有幂等输出的昂贵函数,请缓存结果,以便不必重新计算

我的博客上还有更多的内容(上面的链接)。

这仍然是一个有点尖端的东西,但是Firefox3.5有这些东西叫做Web Workers,我不确定它们在其他浏览器中是否支持

Resig先生在这里有一篇关于它们的文章:


如果您注意到,当工作线程执行请求时(因此不会冻结浏览器),旋转的Firefox徽标不会冻结,那么这可能是最简单的例子。

我的经验是,DOM操作,特别是在IE中,对性能的影响要比“核心”JavaScript(循环等)大得多


如果您正在构建节点,那么在IE中,通过构建HTML字符串,然后在容器上设置innerHTML,比使用诸如createElement/appendChild之类的DOM方法要快得多。

您可以尝试通过

 $(xmlDoc).find("Object").each(function(arg1) {
    (function(arg1_received) {
                setTimeout(function(arg1_received_reached) {

                    //your stuff with the arg1_received_reached goes here 

                }(arg1_received), 0)
            })(arg1)
}(this));
或者对于“for”循环,请尝试

for (var i = 0 ; i < 10000 ; i = i + 1) {
    (function(arg1_received) {
        setTimeout(function(arg1_received_reached) {

            //your stuff with the arg1_received_reached goes here 

        }(arg1_received), 0)
    })(arg1_to_send)
}
for(变量i=0;i<10000;i=i+1){
(功能(接收到arg1_){
设置超时(函数(arg1\u已接收\u已到达){
//你收到的带有arg1的物品放在这里
}(接收到arg1_),0)
})(arg1_至_发送)
}

我也遇到了同样的问题,我的客户将此报告为“Kill page”错误。但现在我找到了一个最好的解决方案。

如果使用
setTimeout(泵,0),您知道这是否仍然有效吗
?或者这可能会继续抢占响应鼠标输入、更新进度表或其他DOM元素的浏览器代码吗?@Andy Yes
setTimeout
,使用0也会有帮助。请参阅的一些答案。很好,它现在肯定应该在顶部。无论你做什么,使用setTimeout对我来说都很不方便如果您现在在Chrome Windows上转到codepen.io,并执行一个复杂度为O(N!)的算法,例如查找字符串“ABCDEFGHIJKLMNOP”的所有排列,您的浏览器将锁定并变得无响应。在工作线程中,UI会自行运行。这显然是正确的答案。我将此标记为适度…我们将看看会发生什么。