skip to Main Content

I have a function called chat chattext, which purposes is to write text to a box letter by letter.

function chattext(chat) {
  playaudio("talking.mp3");
  document.getElementById("chat").style.display = "block";
  document.getElementById("chat").innerHTML = "";
  var count = 0;
  function update() {
    console.log(count);
    document.getElementById("chat").innerHTML += `${chat.substring(
      count - 1,
      count
    )}`;

    if (++count < chat.length) {

      setTimeout(update, 50);
    } else {
    }
  }
  update();
}

And in another file I execute it like chattext("hello world")
which works fine, but if I execute it something after that like
like

chattext("hello world")
chattext("hi")

it will do both at the same time and output "hhello worl"
not wanted result
so im wondering how can I make it so the 2nd execution of the function will wait for the first to finish?

2

Answers


  1. As it is, you have no way of knowing when a single invocation of chattext has finished, and if you call it twice in succession (while one is still busy), both invocations will "fight" over the text field.

    You’ll have a better time turning it into an async function, which will also mean you’ll need an async delay function, provided below.

    And naturally the function(s) you call that function from will need to be async so you can await for chattext‘s completion.

    function delay(ms) {
      return new Promise(resolve => setTimeout(resolve, ms));
    }
    
    async function chattext(chat, ms=50) {
      chat = String(chat);
      var el = document.getElementById("chat");
      for(let i = 0; i < chat.length; i++) {
        el.innerHTML += chat[i];
        await delay(ms);
      }
    }
    
    async function main() {
      await chattext("Hello, world!n");
      await delay(1000);
      await chattext("It's a nice day, isn't it?nn");
      await delay(1000);
      await chattext("You have nowhere to run.n", 200);
    }
    
    main();
    #chat {
      background: #333;
      color: pink;
      font-family: monospace;
      white-space: pre;
      line-height: 1.5;
      padding: 1em;
      font-size: 15pt;
      text-shadow: red 1px 0 10px;
    }
    <div id="chat"></div>
    Login or Signup to reply.
  2. One option is to put the words to print into an array and constantly check the array.

    const words = [];
    let wordIndex = 0;
    const display = document.querySelector("div");
    
    setInterval(() => {
      if (words.length) {
        display.innerHTML += words[0][wordIndex++];
        if (wordIndex == words[0].length) {
          words.shift();
          wordIndex = 0;
          display.innerHTML += '<br>';
        }
      }
     }, 100);
      
    document.querySelector("button").onclick = () => {
      const txt = document.querySelector("input");
      words.push(txt.value || " ");
      txt.value = "";
    };
    <input type="text"><button>Show</button>
    <div></div>

    You could optimize this by clearing the interval when the list is empty and restarting it when adding a word to an empty list.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search