What is the best way to patiently wait for lines to be printed out one by one

I am in the process of creating my own personal website with a terminal-style design, and I'm looking to showcase a welcome banner followed by a welcoming message. The effect I have in mind involves lines appearing individually from top to bottom and characters revealing themselves from left to right (Check it out here).

However, I've encountered an issue where the welcome banner and message are getting mixed up during display. I would like to ensure that the banner finishes printing before the message starts. Despite trying to use await/async functions in my code, something seems to be off...

Below is a simple example highlighting the problem. Ideally, all lines containing the character "a" should be displayed before those with the character "b". Can you help me identify what's causing this mix-up?

banner = ["aaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaa"]
welcomeMsg = ["bbbbbbbbbbbb", "bbbbbbbbbbbb", "bbbbbbbbbbbb", "bbbbbbbbbbbb"]
var before = document.getElementById("before");

setTimeout(async function() {
  await loopLines(banner, "", 80);
  loopLines(welcomeMsg, "", 80);
}, 100);

async function addLine(text, style, time) {
  var t = "";
  for (let i = 0; i < text.length; i++) {
    if (text.charAt(i) == " " && text.charAt(i + 1) == " ") {
      t += "&nbsp;&nbsp;";
      i++;
    } else {
      t += text.charAt(i);
    }
  }
  setTimeout(function() {
    var next = document.createElement("p");
    next.innerHTML = t;
    next.className = style;

    before.parentNode.insertBefore(next, before);

    window.scrollTo(0, document.body.offsetHeight);
  }, time);
  return;
}

async function loopLines(name, style, time) {
  for (var i = 0; i < name.length; i++) {
    await addLine(name[i], style, i * time);
  }
  return;
}
p {
  display: block;
  line-height: 1.3em;
  margin: 0;
  overflow: hidden;
  /* white-space: nowrap; */
  margin: 0;
  letter-spacing: 0.05em;
  animation: typing 0.5s steps(30, end);
  /* font-size: calc(2vw + 7px); */
  font-size: min(20px, calc(1.5vw + 7px));
}
@keyframes typing {
  from {
    width: 0;
  }
  to {
    width: 100%;
  }
}
<a id="before"></a>

Answer №1

Within the function addLine, there is an absence of the await keyword. Instead, the function calls setTimeout, which does not return a promise that can be awaited. As a result, the promise returned by addLine resolves instantly without waiting for the timeout to finish.

To rectify this issue, a promisified version of setTimeout should be utilized. The definition for this modified version has been included at the beginning of the code snippet below. Afterwards, locate where addLine is being used and substitute setTimeout with the newly defined function:

const delay = ms => new Promise(resolve => setTimeout(resolve, ms));

banner = ["cccccccccccc", "cccccccccccc", "cccccccccccc", "ccccccccccccc"]
welcomeMsg = ["ddddddddddddd", "ddddddddddddd", "ddddddddddddd", "ddddddddddddd"]
var before = document.getElementById("before");


setTimeout(async function() {
  await loopLines(banner, "", 80);
  loopLines(welcomeMsg, "", 80);
}, 100);

async function addLine(text, style, time) {
  var t = "";
  for (let i = 0; i < text.length; i++) {
    if (text.charAt(i) == " " && text.charAt(i + 1) == " ") {
      t += "&nbsp;&nbsp;";
      i++;
    } else {
      t += text.charAt(i);
    }
  }
  await delay(time);  // <---------------
  var next = document.createElement("p");
  next.innerHTML = t;
  next.className = style;
  before.parentNode.insertBefore(next, before);
  window.scrollTo(0, document.body.offsetHeight);
}

async function loopLines(name, style, time) {
  for (var i = 0; i < name.length; i++) {
    await addLine(name[i], style, i * time);
  }
}
p {
  display: block;
  line-height: 1.3em;
  margin: 0;
  overflow: hidden;
  /* white-space: nowrap; */
  margin: 0;
  letter-spacing: 0.05em;
  animation: typing 0.5s steps(30, end);
  /* font-size: calc(2vw + 7px); */
  font-size: min(20px, calc(1.5vw + 7px));
}
@keyframes typing {
  from {
    width: 0;
  }
  to {
    width: 100%;
  }
}
<a id="before"></a>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is preventing me from creating accurate drawings on canvas?

I'm currently working on a paint application and facing an issue. When I place the painting board on the left side of the screen, everything works fine and I can draw without any problems. However, when I move it to the right side of the screen, the m ...

Display the Bootstrap datepicker within an h4 element set to default to today's date, utilizing both Angular and jQuery

Utilizing Boostrap datepicker to obtain the selected date from the calendar and insert it into an <h4> html tag. However, my goal is to display today's date by default in the h4 when it opens for the first time. Using angular.js + jquery f ...

What is the correct method to remove an item from local storage?

Using localStorage, I have stored multiple objects in an array. Is there a way to remove just one object from this array? If I use localstorage.removeItem(keysofthelocalstorage), I can delete the entire array, but I specifically want to remove only certai ...

Tips for keeping several buttons in the spotlight: HTML/CSS/JS

Looking for a solution to keep multiple buttons toggled on? I'm not very familiar with JavaScript, but I know that adding a class on click won't work if there's already a class set. Maybe giving the element an ID could be a possible solution ...

Issue: Unhandled promise rejection: BraintreeError: The 'authorization' parameter is mandatory for creating a client

I'm currently working on integrating Braintree using Angular with asp.net core. However, I've encountered an issue that I can't seem to solve. I'm following this article. The version of Angular I'm using is 14, and I have replicate ...

Is it possible to simultaneously play several one-shot sound effects on mobile web browsers?

I'm attempting to trigger a sound effect when the user clicks a button on my web application. Initially, I experimented with this approach: var sound = new Audio("soundeffect.ogg"); function clickHandler(){ sound.play(); } Unfortunately, if the ...

Error encountered in onclick handler due to unterminated string literal in PHP and jQuery

Trying to utilize PHP to send variables into the onclick of an element is resulting in an "Unterminated string literal" error due to long strings. Below is a snippet of my PHP code: $query = $conn->prepare("SELECT Name, Image, Description, Link, Price, ...

Is your Angular2 form page experiencing reloading issues?

I am currently incorporating Angular2 into my project. I am facing an issue where the page keeps refreshing, and I'm unable to determine the cause. Below is a snippet of my form: <form> <div class="form-group"> ...

Error message received from GitHub when attempting to create a repository through the REST API states that JSON cannot

I am currently in the process of learning how to use REST APIs for GitHub, and my current project involves creating a new repository using JavaScript. Below is the function I have written for this purpose, which includes generating a token and granting all ...

Unable to modify translation values in an existing ngx-translate object

I am facing an issue where I am unable to change the value of an object property within a translation JSON file using ngx translate. Despite attempting to update the value dynamically when receiving data from an API, it seems to remain unchanged. I have t ...

Guide on using Ajax and spring MVC to dynamically fill a modal form

One JSP page displays database results in a table on the browser, allowing users to edit or delete each row. I want to implement a feature where clicking the edit link fetches specific customer data from the database using Spring MVC and Hibernate, display ...

Tips for monitoring input content "live"

Currently, I am in the process of developing a web form that includes a text field intended to receive numeric values. If the user enters non-numeric characters into this field, the form will not submit. However, there is no error message displayed to noti ...

Delivering XML in response to a webmethod call

While working with an ajax PageMethod to call an asp.net webmethod, I encountered an issue when trying to pass a significant amount of XML back to a callback javascript function. Currently, I am converting the XML into a string and passing it in that form ...

Newbie mishap: Utilizing an array retrieved from a function in javascript/jquery

After submitting the form, I call a function called getPosts and pass a variable str through it. My aim is to retrieve the data returned from the function. // Triggered upon form submission $('form#getSome').submit(function(){ var str = $("f ...

Learning the art of Javascript programming within the HTML5 realm

Seeking assistance with a JavaScript project - I'm attempting to develop a Bubble Buster game reminiscent of pong, but with multiple bubbles. The goal is to have falling bubbles on screen (roughly 100 in total) in various colors dropping from random l ...

Incorporate additional form element functionalities using radio inputs

Recently, I created code that allows a user to duplicate form elements and add values by clicking on "add more". Everything is functioning properly except for the radio inputs. I am currently stuck on this issue. Does anyone have any suggestions on how I c ...

React treats flat arrays and nested arrays in distinct ways

After some experimentation, I discovered an interesting behavior in React when passing nested arrays. Surprisingly, React renders the items properly without complaining about missing keys on the elements. const stuff = 'a,b,c'; // Nested Array ...

The i18n feature in node.js seems to be malfunctioning as the setLocale function is not working properly. Regardless

Something seems off with my usage of the i18n library, but I believe I'm following the correct steps. I've been attempting to switch the locale. Here's my current code. Despite calling setLocale on the global i81n variable, it continues to ...

"Transmitting a message with socket.io upon establishing connection

Currently getting the hang of socket.io and giving it a try. I have a straightforward app where clicking the display button shows an image on the screen in real time. I have a couple of questions. Firstly, my main concern is regarding the synchronization ...

incorrect encoding of Greek characters due to the multer upload package

When uploading files with Greek characters, the uploaded titles are saved as ΠÏξ Îαξ & ÎαÏÏιμιÏαίοι Here is the code for multer variables inside a js file: const storage = multer.diskStorage({ destination: f ...