2012-02-28 14 views
4

私のページには〜9000個の要素があり、頻繁に再構築する必要があります。数秒かかることがあります。大きなループが続くDOM更新が時間内にレンダリングされない

私はLoading..で要素をカバーする小さなオーバーレイウィジェットを作った。メッセージ。要素を再構築する直前にshowOverlay()と呼び出し、ループの後にhideOverlay()を呼び出します。

しかし、私のLoading...メッセージが表示される前にループがページをロックするので、決して表示されません。

function rebuild() { 
    showOverlay(); // The overlay never appears... 
    for (var i=0;i<9000;i++) { 
    // append element... 
    } 
    hideOverlay(); 
} 

ループを開始する前にオーバーレイがレンダリングされるのを待つ方法はありますか?

答えて

3
function do_rebuild() { 
    for (var i=0;i<9000;i++) { 
    // append element... 
    } 
    hideOverlay(); 
} 


function rebuild() { 
    showOverlay(); // The overlay will appear 
    window.setTimeout('do_rebuild();',1); 
} 

私が知っている唯一のクロスブラウザ方法です。

+0

は十分であることが保証さ1ミリ秒ですか? –

+0

@TonyRあまり時間がかかるはずはありませんが、10時に設定します。IIRC Google Chromeは最低でも10を使用するため、1msにしてもまだ待機します。 10ms。これはまだページをフリーズします。 –

+0

どれくらい時間がかかりますか?1msで十分かもしれません。重要なのは、 "スレッドスイッチ"に類似したものを強制することです(単語の一般的な意味でのスレッド切り替えでない場合でも)。 - JSタスクを脇に置いてDOMタスクを開始します。タイムアウトはそれを中断しますが、遅れることがあります。 –

1

ループを設定タイムアウトの内側に配置して、ページを保持しないようにする必要があります。あなたのオーバーレイが表示されていても、誰も

var counter = 0; 
function rebuild() { 
    showOverlay(); 
    doWork(); 
} 
function doWork() { 
    if(counter < 9000){ 
     // append element 
     counter++; 
     setTimeout(function(){ 
      doWork(); 
     },10); 
    } 
    else { 
     hideOverlay(); 
    } 
} 

EDITを凍結自分のページを好きではない:この答えは、実際にかかわらず、ページを処理するために非常に時間がかかります。 90秒という非常に受け入れ難い領域のどこかで、もう1つの方法は、100回の繰り返しごとにタイムアウトを設定することです。これにより、合計ロード時間に約1秒が追加されますが、ページがフリーズしないようにする必要があります。

function doWork() { 
    if(counter < 9000){ 
     // append element 
     if(counter % 100 == 0) { 
      setTimeout(function(){ 
       doWork(); 
      },10); 
      counter++; 
     } 
     else { 
      doWork(); 
      counter++; 
     } 
    } 
    else { 
     hideOverlay(); 
    } 
} 
+0

これは、10ミリ秒だけ全体を遅らせていませんか?私にはまだ9000反復ループが続いているようです。 –

+0

ああ、私は今見て、それは次の開始前に10ミリ秒前の反復を与える...うーん私はそれを試してみましょう! –

+0

ええ、私の第2のものを試してください、最初のものは永遠に取るでしょう。 –

0

その他の回答は、タイマーを使用して「擬似スレッド」方法でこれを行う方法を示しています。

その間、私はWeb Workersについて学びました。これは、スクリプトの実行とDOM更新を分離するスレッド化ソリューションです。

彼らが現在のWebKitとFirefoxでサポートされており、サポートはIE 10

+0

WebワーカーはDOMにアクセスできません。解決策は良いですが、私は恐れています、それは問題に適合しません。 –

0

のために計画されたあなたはこの試みることができる:

var loopCount = 0, 
    build = function() { 

    var frgm = document.createDocumentFragment(); 
    for (var i = 0; i < 200 && loopCount < 9000; i++) { 
     // some codes 
     frgm.appendChild(someElement); 
     loopCount ++; 
    } 
    parentNode.appendChild(frgm); 

    if (loopCount < 9000) { 
     setTimeout(build, 10); 
    } 
}; 

function rebuild() { 
    showOverlay(); // The overlay never appears... 
    build(); 
    hideOverlay(); 
} 
関連する問題