はい、あなたは基本的な何かを見逃しています:あなたのコードがブラウザに制御を戻すまで、ブラウザはそれ自身の仕事をしません。
次のようなコードを考えてみましょう。
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ブロッカーを追加することをお勧めします。