是的,您缺少一些基本的东西:在您的代码将控制权返回给浏览器之前,浏览器不会做任何自己的工作。
考虑一些这样的代码:
collection = [1..1000]
addOne = (index) ->
$('#n').text(index + 1)
percent_complete = ((index + 1) / collection.length) * 100
$("#bar").width("#{percent_complete}%")
addOne(i) for e,i in collection
console.log('done')
您会看到短暂的停顿,然后#bar
会#n
更新并done
出现在控制台中。演示: http: //jsfiddle.net/ambiguous/f5qKV/(您可能需要增加 1000 以使事情更明显)。
但是,如果您setTimeout(..., 0)
在每次迭代时将控制权返回给浏览器:
collection = [1..1000]
addOne = (index) ->
$('#n').text(index + 1)
percent_complete = ((index + 1) / collection.length) * 100
$("#bar").width("#{percent_complete}%")
i = 0
timeOut = ->
if(i == collection.length)
console.log('done')
return
addOne(i++)
setTimeout(timeOut, 0)
setTimeout(timeOut, 0)
您将能够看到#bar
和#n
更改,然后done
当一切完成后您将在控制台中看到。演示:http: //jsfiddle.net/ambiguous/UCbY8/1/
请注意,该setTimeout
版本使用setTimeout
回调来触发下一次超时,以确保一切都以与简单for
或each
循环中相同的顺序发生。
教训是,如果你想使用那种进度指示器,你必须添加一些老式的伪合作多任务处理技巧。
将控制权交还给浏览器也会让您在不期望的情况下接受用户交互。如果你走这条路,你可能想要添加一个通用的 UI 阻止程序,以防止人们在你工作时点击东西。