我正在编写一个javascript程序,其中包含一个非常长时间运行的foreach循环,如下所示:
for (property in object) {
difficultTask();
}
我已经看到你可以用setTimeout
做一些事情,这可以让你定期将控制权交还给浏览器;但是,我还没有看到任何能够使用foreach循环执行此操作,只有带索引的for循环。此外,这些任务不能异步完成,因为每次迭代都取决于前一次迭代的结果。
我能想到的一个解决方案是将我的对象分成很多较小的对象并遍历每个对象,在每个对象之间设置一个超时,但我想看看这是否可行而不诉诸于这一点。
有没有办法在不彻底改变对象的方式的情况下做到这一点?
答案 0 :(得分:4)
将所有属性放入数组中,然后可以使用索引变量和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 :(得分: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);
}
}
答案 2 :(得分:1)
这听起来像使用网络工作者一个有用的点。它们允许并发执行javascript代码。您可能想阅读introduction to webworkers。这篇文章相当古老(现在可能在某些方面已经过时),但仍然很好。
浏览器支持现在为pretty good。如果您需要浏览器支持旧IE,可以使用a polyfill,这样您就可以立即开始使用Web工作。