【问题标题】:How to use setTimeout within a for ( ) { } loop?如何在 for ( ) { } 循环中使用 setTimeout?
【发布时间】:2014-07-08 18:09:56
【问题描述】:

美好的一天!我正在学习 javascript,但计时器有问题。我只是想检查整个页面写入后是否触发了 onload 事件,包括通过 javascipt 修改的文本。为此,我想通过在字符之间引入 200 毫秒的延迟来减慢文本的写入速度。

我使用的测试如下:

<!DOCTYPE html>    
<head>
<meta charset="utf-8">
<title>Onload test</title> 
<script>

    function load() {
        alert("The page is considered loaded !");
    }

    function writeSlowly(text, timer) {
        var L= text.length;
        var st = "";
        function write (seq) {
            document.getElementById("st").innerHTML = seq;
        };
        for (var i = 0; i < L; i += 1) {
            st += text[i];
            setTimeout(write(st), timer);
        };
    };

</script>
</head>
<body>
<p id="st"></p>
<script>
    writeSlowly("This pages takes a while to load", 200);
    window.onload = load;
</script>
</body>
</html>

页面加载就像没有延迟一样。实际上,我预计文本(32 个字符长)大约需要 32 x 200 毫秒 =~ 7 秒。调试时(使用 Firebug - 我使用 Firefox 30),程序会逐行执行,但计时器不起作用。页面几乎立即显示。

【问题讨论】:

  • 谢谢 Adam、Cheruvian 等人。我会进一步练习。
  • 感谢 Cheruvian 和 Adam 花时间编写正确的解决方案。你的两个脚本都在工作。我会确保我理解它的要点。
  • 回到我原来的问题:什么时候考虑加载页面?答案是:很早。它不会等待页面完成执行脚本。您也可以在 Firebug 上的 HTML 选项卡中看到这一点:您可以看到随着时间的推移而扩展的段落:

    This page ... 直到它完成。所以我认为正确的说法是:“当读取静态元素并且读取动态元素的代码但不一定完全执行时,页面被认为已加载。”

  • 当所有静态内容加载完毕后,包括 CSS 文件、图片和 HTML DOM,onload 函数将运行。该页面无法等待 dynamic 元素加载,因为它们是使用脚本完成的,并且无法确定它们何时“完成”加载。 setTimeout 方法是异步的,这意味着其余代码不会等待它运行,而是在没有它的情况下继续运行,这就是window.onload 在字符串输出之前运行的原因。

标签: for-loop callback settimeout


【解决方案1】:

您正在为每个字母创建单独的计时器,都从时间 0 开始,并且都在时间 200 毫秒执行。

此外,setTimeout 的函数需要是一个回调函数(该函数将在计时器到期时回调)。你传递给它一个空值。 write() 不会返回任何东西,更不用说函数了。

所以你实际上是在每次循环时都写每个字母,不会造成延迟

为了实现您正在尝试的目标,我会按照以下方式做一些事情......

var str;
var index = 0;

function writeSlowly(text, timer) {
    str = text;
    setInterval(writeNext, timer);
};
function writeNext()
{
    if(index < str.length - 1)
         document.getElementById("st").innerHTML = str.substring(0, ++index);
    else 
         document.getElementById("st").innerHTML = str;
}

【讨论】:

    【解决方案2】:

    我做了一些修改并成功了,你可以试试at this link

    一个问题是您调用了write 函数,而不是将其设置为回调。另一个问题是你想写的字符串在你写之前就被填满了。最后,所有写入的计时器都设置为距当前时间 200 毫秒,而不是为每个写入的字符引入 200 毫秒的延迟。

    更新的 Javascript 如下。

    function writeSlowly(text, timer) {
        var L= text.length;
        var st = "";
        var delay = 0;
        for (var i = 0; i < L; i += 1) {
            st += text[i];
            delay += timer
            setTimeout(writer(st), delay);
        };
    }
    
    function writer(toWrite) {
        return function() {
            document.getElementById("st").innerHTML = toWrite;
        }
    }
    

    编辑:
    我更新了the JSFiddle

    当文本完成滚动时,它将触发done() 函数并运行您想在该点运行的任何代码。

    【讨论】:

      【解决方案3】:

      根据给出的答案,他们的分析(请参阅原始问题下方的 cmets)我的首选答案如下 - 就像 Adam 的答案一样 - 对于 2880 个字符的字符串,每个字符延迟 2 毫秒几乎需要 5760 毫秒。中心部分在下方和full answer on JS Fiddle

      function writeSlowly(text, timer) {
          var L= text.length;
          var delay = 0;
          for (var i = 0; i < L; i += 1) {
              setTimeout(writer, delay += timer);
          };
          function writer() {
              if (!writer.seq) writer.seq = 0;  // Create a function property that increments on each call.
              document.getElementById("slowpara").innerHTML = text.substring(0, ++writer.seq);
          }
      }
      

      感谢 StackOverflow 和社区,特别是 Cheruvian 和 Adam 的慷慨帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-05-02
        • 2015-04-26
        • 1970-01-01
        • 2019-10-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-21
        相关资源
        最近更新 更多