2011-04-21 39 views
2

我有一个循环,应该更新循环 增量的进度条,但它只是在循环实际完成后一次着色进度条。我记得有一个类似的问题,如果我使用警报语句,着色会起作用,所以我认为它与线程的并发性有关。为了解决我的老问题,我使用了setTimeout。但是,这仍然没有让我的进度条实时着色。Javascript进度条不会更新'即时进行',而是一旦进程完成后全部进行更新?

下面是我在做什么:

for (var i = 0; i < numOfRows; i++) { 
    setTimeout('ColourBlock(' + i + ')', 0); 

    // do_work 
} 

function ColourBlock (position){ 
    document.getElementById("block" + position).style.backgroundColor = "orange"; 
} 

有人告诉我,这可能是由于JavaScript的优化?任何人都可以帮忙吗?

回答

4

这不是线程。这是关于这样一个事实,即当代码快速地进行DOM或样式更改时,浏览器不会尝试更新每个DOM之间的视图。相反,它等待事情冷静下来,然后重新绘制。

如果您按照每次更改以非零超时值(例如100毫秒)描述的顺序对代码进行了编码,则会发生这种情况。正如你所写的那样,在零毫秒超时的情况下,所有的更新都会在很短的时间内发生 - 除非你有成千上万个这样的块,否则可能会在毫秒级之内。 (请注意,您的示例代码不会给出100作为每次更改的超时时间;您必须将它们逐渐增加到将来,每增加一个100,或者您可以使用间隔计时器和在上次更新后取消)

+2

这有没有关系快速变化或优化和所有做的事实是,JavaScript代码和UI运行在同一线程上;因此在执行js代码时UI不能更新。增加超时将无助于你,除非你增加超过功能执行时间,此时你已经完成了,并且不再需要进度条了。 – Luc 2011-04-21 12:13:09

+0

@Luc增加超时一定会有所帮助。对所有这些使用超时值为零将导致事件循环完成后立即触发定时器事件。较大的超时值肯定会允许浏览器刷新视图。正如你可以在[这个jsfiddle示例](http://jsfiddle.net/vcUs3/)中看到的,即使1毫秒的延迟也会允许可见的动画。 – Pointy 2011-04-21 12:26:07

+0

谢谢你,你是对的。但是,问题是我现在不得不'时间'什么时候该做什么,这应该告诉客户这个过程需要多长时间。我可以强制我的进度条完成10秒,并且该过程可能在4秒后完成:s – James 2011-04-21 12:36:57

3

浏览器在执行javascript代码时不会更新UI。当代码完成并且控制权返回到UI时,更新将一次全部发生。

这也是它使用警报的原因 - 当警报加强时,javascript执行被暂停并且控件返回到UI。

0

尝试增加setTimeout期间的时间。当我遇到类似的问题时,我们使用了200毫秒的差距,并且工作。

1

您需要使用闭包,以便在致电ColourBlock时使用值i(在下面的代码中将其分配给currentPosition)。试着改变你的for环路是这样的:

for (var i = 0; i < numofrows; i++) { 
    (function() { 
     var currentPosition = i; 
     setTimeout(function() { 
      ColourBlock(currentPosition); 
     }, 500); 
    })();