【问题标题】:Javascript: How to put a simple delay in between execution of javascript code?Javascript:如何在执行 javascript 代码之间设置一个简单的延迟?
【发布时间】:2011-06-22 05:02:28
【问题描述】:

我有一个 for 循环,它在 javascript 代码中迭代超过 10,000 次。 for 循环创建 标签并将其添加到当前页面 DOM 中的框中。

for(i = 0; i < data.length; i++)
{
    tmpContainer += '<div> '+data[i]+' </div>';
    if(i % 50 == 0) { /* some delay function */ }
}
containerObj.innerHTML = tmpContainer;

我想在每 50 个 标签之后放一个延迟,那么该位置的代码是什么

/* some delay function */

因为加载所有 10,000 个

标签需要花费太多时间。我想以 50 个 标签块的形式更新该框。

提前致谢。

【问题讨论】:

    标签: javascript javascript-framework


    【解决方案1】:

    您可以使用window.setTimeout 函数来延迟某些代码的执行:

    if(i % 50 == 0) {
        window.setTimeout(function() {
            // this will execute 1 second later
        }, 1000);
    }
    

    但您的 javascript 将继续执行。它不会停止。

    【讨论】:

      【解决方案2】:

      在这些情况下有一个方便的技巧:使用 0 毫秒的 setTimeout。这将导致您的 JavaScript 屈服于浏览器(因此它可以执行其渲染、响应用户输入等),但不会强制它等待一定的时间:

      for (i=0;i<data.length;i++) {
          tmpContainer += '<div> '+data[i]+' </div>';
          if (i % 50 == 0 || i == data.length - 1) {
              (function (html) { // Create closure to preserve value of tmpContainer
                  setTimeout(function () {
                      // Add to document using html, rather than tmpContainer
      
                  }, 0); // 0 milliseconds
              })(tmpContainer);
      
              tmpContainer = ""; // "flush" the buffer
          }
      }
      

      注意:T.J. Crowder 在下面正确地提到,上面的代码将在循环的每次迭代中创建不必要的函数(一个用于设置闭包,另一个作为setTimeout 的参数)。这不太可能成为问题,但如果您愿意,可以查看 his alternative,它只创建一次闭包函数。

      警告:尽管上面的代码会提供更愉快的渲染体验,但不建议在页面上使用 10000 个标签。在此之后,其他所有 DOM 操作都会变慢,因为要遍历的元素更多,而且对布局的任何更改都会进行更昂贵的回流计算。

      【讨论】:

      • 可以,但有两个 cmets: 1. 每次达到 50 个 div 时,它都会不必要地创建一个 new 函数。那是 199 个不必要的功能。可能没问题,但仍然可以避免。 2. 将 HTML 构建成一个字符串数组,然后在完成后使用a.join("") 创建一个大字符串,而不是使用字符串连接来构建 HTML。
      • @T.J.你对这两点都是正确的,但为了简单起见,我没有打扰:1.函数创建很少是性能问题,特别是当你的瓶颈是 DOM 时,2.字符串连接只是 IE 上的问题,并且在其他浏览器中通常更快,但即使对于 IE,由于我将 tmpContainer 重置为空字符串,字符串永远不会变大;)
      • @Box9:刚看到:document.write?!?!那绝对行不通。 appendChild等都可以。
      • @T.J.好吧,它会工作,但它只会覆盖您拥有的页面,所以它可能不会按预期工作 ;) 我希望很清楚它只是表明使用变量html 而不是tmpContainer
      • @Box9:对“工作”的有趣解释。 ;-) 我会将其删除,因为它完全具有误导性,并附上评论“在此处使用 html 创建元素”。顺便说一句,我之前错了,它是大约 398 个完全不必要的函数(你正在重新创建 创建 闭包的东西,比另一个更不需要)。此外,除非发生data.length % 50 == 0,否则这将无法输出最后的 1-49,或者至少需要重复的代码才能这样做。取而代之的是:pastie.org/1533736 这是全部,只是为了给出一个好的答案,而不是给你带来困难。
      【解决方案3】:

      我会将创建divs 的代码分解为一个函数,然后通过setTimeout 定期安排该函数的执行,如下所示:

      function createThousands(data) {
          var index;
      
          index = 0;
          doAChunk();
      
          function doAChunk() {
              var counter;
      
              for (counter = 50; counter > 0; --counter) {
                  // Are we done?
                  if (index >= data.length) {
                      // Yup
                      return;
                  }
      
                  // ...create a div...
      
                  // Move to the next
                  ++index;
              }
      
              // Schedule the next pass
              setTimeout(doAChunk, 0); // 0 = defer to the browser but come back ASAP
          }
      }
      

      这使用单个闭包doAChunk 来完成工作。一旦其工作完成,该闭包就有资格进行垃圾收集。 (更多:Closures are not complicated

      Live example

      【讨论】:

      • @fehergeri:我的问题?嗯?
      • @fehergeri:哦,我明白了,你的意思是他的问题。我正在处理不进行临时更新的问题;回流完全是另一回事。
      【解决方案4】:

      需要很多时间,因为回流。您应该创建一个文档片段,然后添加小子。

      When does reflow happen in a DOM environment?

      Javascript Performance - Dom Reflow - Google Article

      睡觉不能解决你的问题

      另一方面,您创建了一个包含innerhtml 和添加到innerhtml 的字符串。字符串的东西真的不需要很大的性能,但是当你执行.innerhtml 命令时,它会启动一个进程,解析你的字符串并创建元素并附加它们。你不能打断或增加延迟。

      innerhtml 进程不能休眠或中断。

      你需要一个一个生成元素,添加50个元素后,创建一个settimeout延迟。

      var frag = document.createDocumentFragment();
      
      function addelements() {
      
         var e;
         for(i=0;i<50;++i) {
             e = document.createElement('div');
             frag.appendChild(e);
         }
         dest.appendChild(frag);
         window.setTimeout(addelements,1000);
      
      }
      

      【讨论】:

        【解决方案5】:

        这是在不挂起浏览器的情况下延迟 javascript 的真正技巧。 您需要使用带有同步方法的 ajax 函数,该函数将调用 php 页面,并且在该 php 页面中您可以使用 sleep() php 函数! http://www.hklabs.org/articles/put-delay-in-javascript

        【讨论】:

        • 请注意 link-only answers 是不鼓励的,所以答案应该是寻找解决方案的终点(而不是另一个参考中途停留,随着时间的推移往往会变得陈旧)。请考虑在此处添加独立的概要,并保留链接作为参考。
        猜你喜欢
        • 1970-01-01
        • 2013-07-26
        • 1970-01-01
        • 2014-06-02
        • 1970-01-01
        • 1970-01-01
        • 2018-02-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多