1

非常にプロセス集約的なJavascriptコードがあり、「応答しないスクリプト」の警告がトリガーされています。コード化された各ステップは、コード化された順序で実行する必要があります。問題のある機能を見つけたと思いますが、警告を発せずに機能させる方法がわかりません。

ここで役立つ可能性のある兆候を見つけました(setTimeout) Javascript:応答しないスクリプトエラー ですが、これは本当にあいまいだったので、探し続けました。これははるかに優れた例ですが、コードにこれを実装する方法がわかり ません。集中的なJavaScript処理中に、ブラウザーに(簡単に)制御を戻すにはどうすればよいですか? 元の記事 http://www.julienlecomte.net/blog/2007/10/28/ はすべてのアカウントの天才によるものですが、ここで実装するためにそれを理解することはできないようです。

これが私が適合を引き起こしていると私が信じるコードです。

// -----------------------------------
//  Output stats for all nations
//  by continent in a colon delimited
//  list further delimited by a ~
//  ( ContinentName:NationPower:NationHTML )
//  expects the output from the 
//  continent_stats function
// -----------------------------------

function Nations(ContinentData) {

    document.write("<tr><th>Nation Stats</th></tr><tr>"); // setup progress bar
    var NationString = ""; // init the string
    var Carray = ContinentData.split("*"); //continents
    for (cit = 0; cit < Carray.length; cit++) { // go through the continents
        var Cstat = Carray[cit].split(":"); // make an array of the individual continent stats
        var NumberOfNations = Cstat[4]; // nation #
        var ContinentName1 = Cstat[0]; // Continent Name
        document.write("<td class='ProgressBarText'>" + ContinentName1 + "</td><td class='ProgressBars'>"); // Format loader screen text
        for (nnum = 0; nnum < NumberOfNations; nnum++) { // go through the number of nations on the continent
            var nat1 = BuildCulture(); // build the nation
            var Natname= "Nation"+padLeft(nnum,2,"0"); // name the nation
            NationString = NationString + ContinentName1 + ":" + Natname + ":" + nat1 + "~"; // build the string
            document.write("█"); // add to progress bar
        }
        document.write("</td><td>"+NumberOfNations+ " Nations</td></tr>"); // progress bar complete
    }
    document.write("</table>"); // end the loader screen table
    // send the nation string back
    return NationString;
}

つまり、大陸を循環し、大陸ごとに国を作成していることがわかります。BuildCulture()関数が原因です。それ自体は問題なく動作しますが、約4大陸のコースで8または9をつなぎ合わせると、警告が鳴ります。

使ってみました

setTimeout( function() { BuildCulture(); }, 1000);

あらゆる場所、メインコードセクション、BuildCulture()関数の開始と終了、Nations(ContinentData)関数のループ内外。それは決して機能しません。

明らかにループが多すぎますが、すべてのループが必要です。SetTimeoutは私を助けてくれますか、それとも間違ったステートメントを追いかけていますか?

SetTimeoutがソリューションのターゲットである場合、このコードでどのように実装できますか?

どうもありがとう。

PS私はこれがFirefoxで動作することだけを目指しているので、IEコアブラウザとの互換性は必要ありません。

4

2 に答える 2

0

まず、ブラウザはシングルスレッドアプリケーションです。すべてのイベント、タイマー、および相互作用は、段階的に線形に実行されます。したがって、新しいスレッドを生成したり、並列計算を実行したりすることはできません。

function Nationsその意味で、setTimeoutは、以前の結果をフィードするsetTimeoutでカットして呼び出すことができれば、仮想的に役立つ可能性があります。しかし、それは最適ではありません;)


第二に、DOMに触れないでください!!!
JSは高速かもしれませんが、DOM(getElements、document.write、innerHTML ...)へのアクセスは遅いです

function Nations(ContinentData)あなたの場合、いくつかのdom要素にinnerHTMLする1つの文字列を出力するように書き直してください。
重要なのは、すべての計算と準備は(比較的)高速なJSエンジンで行われ、結果は非常に遅いDOMに適用またはinnerHTML化されるということです。

または、DOMオブジェクトを使用してcreateElemとaddChildを使用することもできます。関係ない。どちらの方法にも長所と短所がありますが、どちらも同じことをします。


3番目:Webワーカーを試してみてください。彼らは「スレッド」をうまくシミュレートしています:http:
//ejohn.org/blog/web-workers/
http://www.sitepoint.com/javascript-threading-html5-web-workers/
http:// www .w3schools.com / html5 / html5_webworkers.asp

于 2012-07-03T03:57:31.570 に答える
0

どこでもこれを実行できなかったので、いくつかのエラーがあるかもしれませんが、これは、タイムアウトを使用する必要がある場合に使用したいパターンです。

ただし、コードの構造とスタイルを考えると、これについて間違った方法で行っている可能性があるという印象を受けます。

たとえば、データはどこから来ていますか? 構造化データが文字列で表されるのはなぜですか? この計算はすべてクライアント側で行っていますか? ゲームですか?buildCulture()そんなに時間がかかるのは何をしているのですか?いずれにせよ、おそらく JSON と非同期読み込み (別名 AJAX) を調べる必要があります。

function Nation(continentData, renderNationComplete) {
  // begin our table
  var str = '<table>',
      continents = continentData.split('*');

  // use the `+=` operator to add string together
  str += '<tr><th>Nation Stats</th></tr><tr>';

  // This will act like a `for` loop - 
  // the difference is that we can control the iterations
  var continentsCount = 0;
  function renderContinents(){
    if(continentsCount < continents.length) {
      var stats = continent[continentsCount].split(':'),
          nNations = stats[4],
          cName = stats[0];

      str += '<td class="ProgressBarText">' + cName + '</td><td class="ProgressBars">';

      var nationCount = 0;
      function renderNation(){
        if(nationCount < nNations) {
          var culture = BuildCulture(),
              nName = "Nation" + padLeft(nationCount, 2, "0");

          str += cName + ':' + nName + ':' + culture + '~';
          str += '█'; // not precisely sure what this is for.

          nationCount++;
          // renderContinents won't proceed till we're done with all the 
          // renderNations for this particular continent.
          setTimeout(function(){ renderNation(); }, 1000);
        } else {
          // close up the rows
          str += '</td><td>' + nNations + ' Nations</td></tr>';
          nationCount++;
          // this timeout may not be necessary, you'll have to tweak the value.
          setTimeout(function(){ renderContinents(); }, 1000);
        }
      } renderNation();
    } else {
      str += '</table>';

      // everything is done, send it back.
      // note: this function does not return anything,
      // instead, it keeps on running asynchronously till
      // it's done, at which point it call the callback
      // that you pass in when it is instantiated.
      renderNationComplete(str);
    }
  } renderContinents();
}

// here we call the Nation function, and pass in another function
// that we want to be called when everything is done.
// in this case that function returns a string of html, that we can
// then add to the DOM.
Nation(data, function(html){
  var el = document.getElementById('tableArea');
  el.innerHtml(html);
});
于 2012-07-03T06:03:23.113 に答える