【问题标题】:I'm trying to print one letter after another我正在尝试一个接一个地打印一个字母
【发布时间】:2022-02-13 18:36:19
【问题描述】:

我试图一个接一个地打印一个字母,但是这段代码只是等待 100 毫秒,然后打印出没有暂停的值。知道为什么会发生这种情况以及如何解决吗? 代码:

    for (let i = 0; i < welcText.length; i++) {
        setTimeout(()=>{
            welcome.innerText += welcText[i];
        },100);
    }

【问题讨论】:

    标签: javascript html


    【解决方案1】:

    注意setTimeout实际上并没有延迟后面代码的运行;它只是安排将来发生的事情。所以所有的字母会在 100 毫秒后同时添加。

    最直接的解决方法是让每个后续超时等待更长的时间,方法是将延迟乘以字母的索引 (i * 100):

    const welcome = document.getElementById('welcome');
    const welcText = 'Welcome!';
    
    for (let i = 0; i < welcText.length; i++) {
        setTimeout(() => {
            welcome.innerText += welcText[i];
        }, i * 100);
    }
    &lt;div id="welcome"&gt;&lt;/div&gt;

    【讨论】:

    • 为什么不直接使用 setInterval 而不是 setTimeout?
    • @kojow7 这也是可能的,但不如这个简单,因为您需要跟踪其他状态(索引和间隔 id)并在之后取消间隔。当然,请随意将其写成替代答案!
    • 唯一的问题是它为字符串上的每个字符运行一个超时调度程序。如果您的字符串太长,可能会产生性能问题。除此之外,这个答案很棒!
    【解决方案2】:

    以下函数divtxt() 返回一个Promise。您可以使用它将txt 发送到具有给定id 的div,并让每个字母出现在ms 间隔中。并且:您可以使用它构建任意数量的后续操作链:

    function divtxt(id, txt, ms, wait = 0) {
      const div = document.getElementById(id);
      return new Promise((res, rej) => {
        setTimeout(() => { // optional initial timeout, when wait>0
          div.textContent = "";
          const a = txt.split(""),
            iv = setInterval(() => {
              if (a.length)
                div.textContent += a.shift();
              else {
                clearInterval(iv);
                res(txt);
              }
            }, ms);
        }, wait);
      });
    }
    divtxt("welcome", "Hello world, this is my way of doing it! ?", 100)
      .then(prevText => (console.log(prevText + ' is done.'),
        divtxt("descr", "You can also chain this function with any number of consecutive actions."
        +" Now: wait for 2 seconds ...", 100)))
      .then(() => divtxt("welcome", "This promised-based approach REALLY lets you do it!! ??", 50, 2000))
      .then(() => (console.log("ready?"),"Yes! I am REALLY DONE now! ?"))
      .then(console.log)
    #welcome {
      font-weight: 900
    }
    <div id="welcome"></div>
    <div id="descr"></div>

    【讨论】:

      【解决方案3】:

      您可以使用 setInterval 来代替,并使用迭代器每次调用字符串的下一个字符。这有点复杂,但如果字符串太长,它的优点是不会运行多个调度程序。请参阅下面的工作示例。

      const welcome = document.getElementById('welcome');
      const welcomeText = 'Welcome!';
      
      // returns a function that returns the next char in the string everytime its called
      function createIterator(string) {
        let currentIndex = 0;
        return function() {
          return string[currentIndex++];
        }
      }
      // initializes the iterator with the text
      let welcomeIterator = createIterator(welcomeText);
      
      let welcomeInterval = setInterval(function() {
        let nextChar = welcomeIterator();
        // if we finish the string we clear the interval
        if (!nextChar) {
          return clearInterval(welcomeInterval);
        }
        // if the char exists, we append it to the div
        welcome.innerText += nextChar;
      }, 100);
      &lt;div id="welcome"&gt;&lt;/div&gt;

      【讨论】:

        【解决方案4】:

        你也可以这样做

        const welcText = 'Welcome!';
        let i = 0;
        const interval = setInterval(() => {
             if (i >= welcText.length) {
                  clearInterval(interval);
              } else {  
               document.getElementById('helloword').innerHTML += welcText[i];
                i++;
               }
        }, 100);
        &lt;h1 id="helloword"&gt;&lt;/h1&gt;

        【讨论】:

          猜你喜欢
          • 2021-08-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-06-13
          • 2015-09-13
          • 2017-01-10
          • 2010-10-16
          • 1970-01-01
          相关资源
          最近更新 更多