所以我在渲染非常大的集合时尝试显示加载栏。当页面最初加载时,我有一个占位符用于加载栏,我试图像这样更新它:
addAll:
@collection.each(((obj, index) ->
@addOne(obj, index)), this
)
addOne: (obj, index) ->
percent_complete = ((index / @collection.length) * 100)
$(".loading_bar").width("#{percent_complete}%")
# Proceed with rendering, create the view, etc
这里的问题是在addAll
函数完成之前,DOM不会更新。我有一种感觉,这是我不理解一些基本的JS基础知识。任何帮助将不胜感激!
答案 0 :(得分:3)
是的,你遗漏了一些基本的东西:在你的代码将控制权返回给浏览器之前,浏览器不会做任何自己的工作。
考虑一下这样的代码:
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
或{{1}中的顺序相同循环。
如果您想使用这种进度指示器,那么您必须在混音中添加一些旧式伪合作多任务黑客。
将控制权交还给浏览器也会让您在不期望的时候对用户进行交互。你可能想要添加一个通用的UI阻止程序,以防止人们在你工作的时候点击这些东西。