首页 文章

在foreach循环中避免“无响应脚本”消息

提问于
浏览
2

我正在编写一个javascript程序,其中包含一个非常长时间运行的foreach循环,如下所示:

for (property in object) {
    difficultTask();
}

我已经看到你可以用 setTimeout 做一些事情,这可以让你定期将控制权返回给浏览器;但是,我还没有看到任何能够使用foreach循环执行此操作,只有带索引的for循环 . 此外,这些任务不能异步完成,因为每次迭代都取决于前一次迭代的结果 .

我能想到的一个解决方案是将我的对象分成很多较小的对象并遍历每个对象,在每个对象之间设置一个超时,但是我想看看这是否可行而不诉诸于此 .

有没有办法做到这一点,而不会大幅改变我的对象?

3 回答

  • 1

    将所有属性放入数组中,然后您可以使用索引变量和 setTimeout() 遍历数组:

    var props = [];
    for (property in object) {
        props.push(property);
    }
    
    var index = 0;
    function nextChunk() {
        if (index < props.length) {
            difficultTask(object[props[index++]]));
    
            // schedule the next chunk of work after we let the browser process events
            setTimeout(nextChunk, 1);
        }
    
    }
    nextChunk();
    

    您也可以将所有道具放入数组中,这是您不需要IE7或IE8的兼容性:

    var props = Object.keys(object);
    

    根据长时间运行的任务的不同,Web工作者也可能是一个有趣的选项,但在IE 10之前不支持IE .

  • 1

    我认为这个片段可以达到你想要的效果:

    function executeAndSleep(array,currentPos,step,sleepTime){
       for(var i = currentPos;i<currentPos+step&&i<array.length;i++){
          //execute your magic here
       }
       if(currentPos+step<= array.length){
           setTimeout(function(){
                 executeAndSleep(array,currentPos+step,step,sleepTime);
            },sleepTime);
       }
    }
    

    你可以看到它在这里工作http://jsfiddle.net/victorrseloy/3utwF/

  • 4

    这听起来像使用网络工作者一个有用的点 . 它们允许并发执行javascript代码 . 您可能想要阅读introduction to webworkers . 这篇文章相当陈旧(现在可能在某些方面已经过时),但仍然很好 .

    浏览器支持现在是pretty good . 如果您需要浏览器支持旧IE,您可以使用a polyfill,这样您就可以立即开始使用Web worker .

相关问题