1

我有一些非常密集的 Javascript 代码,它触发了“无响应脚本”警告。每个编码步骤都必须按照它们编码的顺序发生。我想我已经找到了有问题的功能,但我不明白如何在不触发警告的情况下使其工作。

我在这里发现了一些可能有帮助的迹象 (setTimeout) Javascript: Unresponsive script error 但这真的很模糊,所以我一直在寻找。这是一个更好的例子,但我看不到在我的代码中实现这一点的方法。 在密集的 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

好的,因为我无法在任何地方运行它,可能会有一些错误 - 但如果你需要使用超时,这是你想要的模式。

但是,鉴于您的代码的结构和风格,我的印象是您可能以错误的方式处理此问题。

例如,您的数据来自哪里?为什么你的结构化数据用字符串表示?您是否在客户端进行所有这些计算?是游戏吗?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 回答
0

首先,浏览器是单线程应用程序。所有的事件、定时器和交互都是线性的,一步一步的。所以你不能产生新线程或进行并行计算。

function Nations从这个意义上说,如果您可以在 setTimeout 中剪切并调用它并为其提供先前的结果,那么 setTimeout 可能会有所帮助。但这不是最佳选择;)


第二,不要碰DOM!!!
JS 可能很快,但接触 DOM(getElements、document.write、innerHTML...)却很

在您的情况下,重写function Nations(ContinentData)以输出一个字符串,您将 innerHTML 到某个 dom 元素。
关键是所有的计算和准备都将在(相对)快速的 JS 引擎中完成,结果将应用于非常慢的 DOM 或 innerHTML-ed。

或者您可以使用 DOM 对象来使用 createElem 和 addChild。没关系。两种方式都有优点和缺点,但都做同样的事情。


第三:尝试使用网络工作者。他们在模拟“线程”方面做得很好: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 回答