【问题标题】:setTimeout in a for loop changes final output; how to delay runs of a for loop, without changing final resultfor 循环中的 setTimeout 更改最终输出;如何在不改变最终结果的情况下延迟 for 循环的运行
【发布时间】:2021-11-09 22:42:18
【问题描述】:

我正在尝试使用 javascript 函数在我的网站上制作自定义打字机效果。为了在每个字母的输入之间添加延迟,我为 for 循环的每次运行实现了一个交错的setTimeout,因此与前一次相比,每次迭代都延迟了 300 毫秒。我需要将特殊字符(' ' 'else if 条件。当排除setTimeout 时,这会产生所需的效果。但是,添加延迟会导致在打印出整个字符后拼出此代码的各个字母。我该如何解决这个问题?

function type(fullTxt, current = '') {
    for (let i = current.length, j = 0; i < fullTxt.length; i++, j++) {
         setTimeout(function() {
            if (fullTxt.substring(i, i+6) === '&nbsp;') {
                console.log(fullTxt.substring(0, i+6));
                i = i + 5;
            } else if (fullTxt.substring(i, i+4) === '&lt;') {
                console.log(fullTxt.substring(0, i+4));
                i = i + 3;
            } else if (fullTxt.substring(i, i+3) === '&gt') {
                console.log(fullTxt.substring(0, i+3));
                i = i + 2;
            } else {
                console.log(fullTxt.substring(0, i+1));
            }
            console.log(j); //included just to ensure j is counting properly
            console.log(i); //included to check progress of loop
            console.log(fullTxt.length); //included to check endpoint of for loop
         }, j * 300);
    }
}

type('hello&nbsp;');

预期输出:

// h
// 0
// 0
// 11
// he
// 1
// 1
// 11
// hel
// 2
// 2
// 11
// hell
// 3
// 3
// 11
// hello
// 4
// 4
// 11
// hello&nbsp;
// 5
// 10
// 11

【问题讨论】:

    标签: javascript for-loop settimeout


    【解决方案1】:

    现在更安全的是使用async/await,调用Promise,这样,你的循环实际上是在等待前一个完成。

    这也使得内容易于编写或以后修改。

    演示的超时设置为2000 ms。

    async function type(fullTxt, current = '') {
        for (let i = current.length, j = 0; i < fullTxt.length; i++, j++) {
                await wait(2000) // Wait for 2000ms
                if (fullTxt.substring(i, i+6) === '&nbsp;') {
                    console.log(fullTxt.substring(0, i+6));
                    i = i + 5;
                } else if (fullTxt.substring(i, i+4) === '&lt;') {
                    console.log(fullTxt.substring(0, i+4));
                    i = i + 3;
                } else if (fullTxt.substring(i, i+3) === '&gt') {
                    console.log(fullTxt.substring(0, i+3));
                    i = i + 2;
                } else {
                    console.log(fullTxt.substring(0, i+1));
                }
                console.log(j); //included just to ensure j is counting properly
                console.log(i); //included to check progress of loop
                console.log(fullTxt.length); //included to check endpoint of for loop       
        }
    }
    
    // Generic Promise function
    function wait(delayInMS) {
      return new Promise((resolve) => setTimeout(resolve, delayInMS));
    }
    
    type('hello&nbsp;');

    【讨论】:

      【解决方案2】:

      您可以只将setTimeout 放在console.log 上,而不是围绕整个if 语句。

      function type(fullTxt, current = '') {
        for (let i = current.length, j = 0; i < fullTxt.length; i++, j++) {
          if (fullTxt.substring(i, i + 6) === '&nbsp;') {
            setTimeout(function() {
              console.log(fullTxt.substring(0, i + 6));
            }, j * 300);
            i = i + 5;
          } else if (fullTxt.substring(i, i + 4) === '&lt;') {
            setTimeout(function() {
              console.log(fullTxt.substring(0, i + 4));
            }, j * 300);
            i = i + 3;
          } else if (fullTxt.substring(i, i + 3) === '&gt') {
            setTimeout(function() {
              console.log(fullTxt.substring(0, i + 3));
            }, j * 300);
            i = i + 2;
          } else {
            setTimeout(function() {
              console.log(fullTxt.substring(0, i + 1));
            }, j * 300);
          }
          setTimeout(function() {
            console.log(j); //included just to ensure j is counting properly
            console.log(i); //included to check progress of loop
            console.log(fullTxt.length); //included to check endpoint of for loop
          }, j * 300);
        }
      }
      
      type('hello&nbsp;');

      【讨论】:

      • 本可以发誓我之前尝试过,但我想没有。它成功了!谢谢一堆。知道为什么我的代码最初在它应该过去的时候一直过去吗?我知道 setTimeout 函数仍然会立即评估所有内容,所以它是否只是提前单独运行所有 else if 条件(不相互检查条件)导致额外结果?
      • @RM7 您必须在变量中传递超时,然后在完成后在其上使用 clearTimeout。但这通常是冻结的来源。如果您非常好奇,我建议您使用类似短哔哔声的声音来清楚地了解发生了什么。
      【解决方案3】:

      您可以使用async 函数实现此目的

       async function type(fullTxt, current = '') {
              for (let i = current.length, j = 0; i < fullTxt.length; i++, j++) {
                   await waitFor(j*300);
                      if (fullTxt.substring(i, i+6) === '&nbsp;') {
                          console.log(fullTxt.substring(0, i+6));
                          i = i + 5;
                      } else if (fullTxt.substring(i, i+4) === '&lt;') {
                          console.log(fullTxt.substring(0, i+4));
                          i = i + 3;
                      } else if (fullTxt.substring(i, i+3) === '&gt') {
                          console.log(fullTxt.substring(0, i+3));
                          i = i + 2;
                      } else {
                          console.log(fullTxt.substring(0, i+1));
                      }
                      console.log(j); //included just to ensure j is counting properly
                      console.log(i); //included to check progress of loop
                      console.log(fullTxt.length); //included to check endpoint of for loop
                   }
              }
          
      
      
      type('hello&nbsp;');
      

      这里是waitFor函数

      function waitFor(ms){
        return new Promise(resolve=> setTimeout(resolve,ms))
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-05-08
        • 2012-06-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多