1

そのため、非常に大きなコレクションをレンダリングするときに、読み込みバーを表示しようとしています。ページが最初に読み込まれるときに読み込みバーのプレースホルダーがあり、次のように更新しようとしています。

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の基本的な基礎を理解していない私だと感じています。どんな助けでも大歓迎です!

4

1 に答える 1

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の場合と同じ順序で発生することが保証されます。foreach

この種の進行状況インジケーターを使用する場合は、昔ながらの疑似協調マルチタスクハックをミックスに追加する必要があるという教訓があります。


コントロールをブラウザに戻すと、予期しないときにユーザーの操作を受け入れることができます。このルートを使用する場合は、作業中に他のユーザーがクリックしないように、一般的なUIブロッカーを追加することをお勧めします。

于 2012-11-05T18:36:04.873 に答える