2011-08-09 6 views
11

私は大きなJSONオブジェクトを持っています。サーバーから戻ってきて、データテーブルを構築してフォームに表示しています。これには通常数秒かかります。ローディングバーを考えていました。 ローディングバーの後ろにロジックがありますが、hmtlデータを作成するループはブラウザをロックしているため、更新が必要な要素を呼び出すことはできません。ここでJavascriptでスレッディングする方法

はこれを行うに私の関数である。

function buildDataTable(db_table, container_id) { 
    var $pb = $("<div id=\"progress-bar\"></div>"); 
    $(container_id).html($pb); 
    $pb.progressbar({ 
     value: 0 
    }); 
    $.post("post location", { 
     view: "all" 
    }, function (data) { 
     var headers = ""; 
     var contents = ""; 
     var jsonObject = $.parseJSON(data); 
     var tik = Math.round(jsonObject.length/100); 
    for (key in jsonObject[0]) { 
      headers += "<th>" + key.replace(" ", "&nbsp;") + "</th>"; 
     } 
     for (i in jsonObject) { 
      contents += "<tr>"; 
      for (j in jsonObject[i]) { 
       contents += "<td class=\"border-right\">" + jsonObject[i][j] + "</td>"; 
      } 
      contents += "</tr>"; 
      if(Math.round(i/tik) == i/tik) { 
/* if I run the alert (between popups) i can see the progressbar update, otherwise I see no update, the progressbar appears empty then the $(container_id) element is updated with the table i've generated */ 
       alert(''); 
       $pb.progressbar("value",i/tik); 
      } 
     } 
     var html = "<table cellpadding=\"5\" cellspacing=\"0\"><thead><tr>" + headers + "</tr></thead><tbody>" + contents + "</tbody></table>"; 

     $(container_id).html(html); 
     $(container_id).children("table:first").dataTable({ 
      "bJQueryUI": true, 
      "sScrollX": "100%" 
     }); 
    }); 
} 
+1

JavaScriptはシングルスレッドです。処理中にGUIを更新できるように、 "setTimeout"を使用して作業を分割して順番に呼び出す必要がありますが、それでもブラウザはやや反応しないように見えます。 – maerics

+0

アニメーションGIFを使用して実際の進捗状況を表示しない方がよいでしょうか? – rlemon

+0

@maerics:非同期リクエストが新しいスレッドを開いたと思いましたか? – Anthony

答えて

19

を[答えとして私のコメントを追加しました]

JavaScriptがシングルスレッドです。あなたの作品を分割し、順番に "setTimeout"を使用して処理中(GUI間での処理中)にGUIを更新できるようにする必要がありますが、それでもブラウザはやはり反応しないようです。

+2

実際に[ウェブワーカー](http://www.whatwg.org/specs/web-apps/current-work/complete/workers.html)は、 'setTimeout'ソリューションの良い代替案を提供しています。 – revers

+0

@リバース:はい、WebWorkersはまさにこの種の問題のために設計されているようです。しかし、それはHTML5のドラフトです(私がチェックした最後の時間)ので、より新しいブラウザにはサポートがありますが、動作に違いがあります。以前のブラウザでは、私が提案したように何かクルージーをやらなければならないでしょう。 – maerics

+0

はい、あなたは正しいです。それはIEがバージョン10より前にそれをサポートしていないようだ... – revers

3

あなたはWebWorkerを使用して試すことができます:https://developer.mozilla.org/en/DOM/Worker
したがって、ワーカーは、メインスレッドの並列に実行されている、あなたは正確に労働者を使用してマルチスレッドを達成することはできません:あなたは労働者からのUIを変更することはできません。
作業者のグリッドを文字列として作成し、作業者が終了したら、必要な場所にグリッドを追加することができます。

+0

HTTPセキュアで問題が発生しているようです... httpsのページを読み込めません – rlemon

+0

[このページ](http://www.html5rocks.com/jp/tutorials/workers/)をご覧ください。基本/#toc-enviornment-subworkers)を入力します。しかし、マーケティング担当者が言及しているように、Webワーカーは新しいものであり、新しいブラウザでのみサポートされています。 – revers

2

setTimeoutでデータベースのすべてのビルドを行う場合、残りのページは応答可能である必要があります。

この関数でhtml要素を構築することができます.HTML要素を準備するには、その要素をDOMに接続します。また、プログレスバーの表示を更新するために、関数を呼び出すか、イベントを送信する必要があります。コメントの後

編集:

これは、バックグラウンドで実行され、ページの応答性には影響しません。

window.setTimeout(function() {buildDataTable(db_table, container_id)}, 0);

あなたはすでにあなたの関数からあなたのプログレスバーを更新するので、これがすべきそれをやる。

ただし、プログレスバーを更新するコードからデータテーブルを生成するコードを切り離したい場合があります。

+0

これを確認できますか? setTimeout(function(){** Function Call **}、0)で関数呼び出しをラップします。 – rlemon

+0

buildDataTableが長時間実行されている(OPがそうだと言う)場合、この方法では応答しないUIの問題が解決されず、実行中にブロックされます。タスクをより小さなチャンクに分割し、それぞれのタイムアウトを得るためにsetTimeoutを呼び出す必要があります。 – UpTheCreek

0

私のアプリケーションでこれを行う唯一のきれいな方法は、サーバー上でjsonを処理し、そこにhtmlを構築することです。 $.post()

を介してブラウザにHTMLを返します。進行状況バーが失われます。しかし、私は無限のロードGIFを使用することができます...

関連する問題