【问题标题】:Monitoring a long task in Javascript用 Javascript 监控一个长任务
【发布时间】:2009-07-15 11:40:37
【问题描述】:

我有一个特定的页面,它使用了许多必须由 Javascript 例程初始化的小部件(大约 400 个,这是一个复杂的小部件)。这需要一些时间(在较慢的机器上甚至需要 20 秒)。现在我想我可以显示一个进度指示器(一个带有百分比标签的简单文本字段),而不是页面,但我发现即使我不断更新它,正在进行的任务也会阻止一切,我看不到任何更新。所以一切都保持冻结,直到繁重的 javascript 任务完成。我什至做了以下实验,但也死机了(firefox 说脚本需要很长时间才能完成......):

function a(){
    for (var i = 0; i < 5000000000000000; i++){
        abb = i;        
    }
}

var abb;

function c(){
    var ef = document.getElementById("pip");
    ef.innerHTML = abb;

}

function b(){

    setInterval(c, 50);
    setTimeout(a, 1000);
}

我想到的唯一解决方案是将长期工作分解并更新标签....但我想知道是否还有其他解决方案!天哪,JS需要线程尽快... :)

有什么想法吗?

【问题讨论】:

    标签: javascript concurrency long-integer task


    【解决方案1】:

    我可以假设脚本是从 onLoad 事件中执行的,这样用户在运行时就不会坐在空白页上吗?

    如果是,那么我建议将脚本分解为单独的函数,创建这些函数的数组,遍历该数组并评估函数,并在每 N 个函数后更新进度指示器。

    如果它是一个面向公众的网站,请尽量减少体验页面所必需的 JavaScript 数量。以及每个小部件需要的初始化量。套用史密斯特工的话说:如果没有人等着看,手风琴折叠树有什么用?

    【讨论】:

    • 很遗憾,您的解决方案不起作用。原因是直到 long job 函数返回,即使它调用其他函数,也不会更新任何内容(至少在 FF 上)。唯一的方法是保留一个全局变量,然后像这样继续: - 从 1 到 20 做事情,更新计数器,setTimeout(比如 1ms,只是为了抢占)然后返回 - 在回调时,从 21 到做事情40、setTimeout 等等……我认为这是让这项工作正常工作的唯一方法,即模拟分时。
    • ...这正是我描述的解决方案
    • 那么抱歉,因为我误解了你:D 无论如何,我正在尝试与此混合的 courotine 东西......如果开发得当,可能是一个很好的工具......我会告诉你的!
    【解决方案2】:

    如果您想要线程,您可以使用 LiveConnect 并创建真正的 Java 线程(如果安全管理器允许的话)。

    如果没有,你可以使用 C 的协程设计模式。

    问候。

    【讨论】:

      【解决方案3】:

      这可行,假设你必须调用 b 来启动它并有一个 id = "pip" 的 div

      <html>
      <head>
          <script type="text/javascript">
      
          var i;
          var state = 0;
      
          function a(){
      
              switch(state){
      
              case 0:
                  i = 0;
              case 1:
                  i++;
                  for (; i < 5000000000000000; i++){
                      abb = i;
                      if (i%1000 == 0){
                          setTimeout(a, 1);
                          state = 1;              
                          return;             
                      }                   
                  }
              break;
              }
          }
      
          var abb;
      
          function c(){
              var ef = document.getElementById("pip");
              ef.innerHTML = abb;
      
          }
      
          function b(){
      
              setInterval(c, 50);
              setTimeout(a, 1000);
          }
      
          </script>
      </head>
      <body onload="javascript:b();">
          <div id = "pip">test</div>
      </body>
      </html>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-12-21
        • 2016-01-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多