Skip to content
Advertisement

Set timeout function not slowing down

I am trying to create a loading screen and have different sets of text show up while it’s loading, but when I increase the rate to 5 secs, the function skips to the last set of loading screen text and doesn’t show the other sets. How can I solve this issue?

JS:

const loadingDiv = document.getElementById('loading-text')

let intervalTimerId = setTimeout(function start() {
    console.log('start');
    intervalTimerId = setTimeout(start, 1000); // (*)

    loadingDiv.textContent = "Welcome To StudioPick." (start, 5000); 

    loadingDiv.textContent = "Loading studios..." (start, 5000);
    loadingDiv.textContent = "Almost done..." (start, 5000); 
    loadingDiv.textContent = "Let's get started" (start, 5000);

    document.addEventListener('DOMContentLoaded', (event) => {
        console.log('all contents loaded in the dom');
    });


    
}, 1000);

setTimeout(function () {
    show('page', true);
    show('loading', false);
});

Advertisement

Answer

There are two issues in your code.

  1. We don’t see where you are waiting for the dom loaded event, since we can’t verify we need to ensure that you have guarded your dom accesses by the DOMContentLoaded event. If you missed this step then the updates would not happen.
  2. The ordering of your setTimeouts based on reading it seems like you want one after another of these messages to display. As written in the question these would all effectivly run at the same time.

The best way to address this issue is use JS promises if available in your target browser (probably works unless you need IE compatibility and cannot load a polyfill).

A partial solution I made to use promises can be read below.

Promises are the best approach for these chained events

index.html

<div id="loading-text"></div>

index.js

function timeout(ms) {
  return new Promise((resolve, reject) => setTimeout(resolve, ms));
}
function loadingScreen() {
  var loadingText = document.getElementById('loading-text');
  loadingText.innerText = "Welcome To StudioPick."
  var delay = 1000;
  return timeout(delay)
    .then(() => { loadingText.innerText = "Loading studios..."; return timeout(delay) })
    .then(() => { loadingText.innerText = "Almost done..."; return timeout(delay) })
    .then(() => { loadingText.innerText = "Let's get started"; return timeout(delay) })
    .then(() => { loadingText.style.display = "none" })
}
document.addEventListener('DOMContentLoaded', () => {
  loadingScreen();
});

If you were to paste these two into codepen.io or a similar site you will see that we iteratively step through each message.

The alternative to fix your setTimeout would to nest the setTimeout calls.

Alternative for browser compatibility

function loadingScreenWithNestedSetTimeout() {
  var loadingText = document.getElementById('loading-text');
  loadingText.innerText = "Welcome To StudioPick.";
  var delay = 1000;
  setTimeout(() => {
    loadingText.innerText = "Loading studios...";
    setTimeout(() => {
      loadingText.innerText = "Almost done...";
      setTimeout(() => {
        loadingText.innerText = "Let's get started";
        setTimeout(() => {
          loadingText.style.display = "none";
        }, delay);
      }, delay);
    }, delay);
  }, delay);
}
document.addEventListener('DOMContentLoaded', () => {
  loadingScreenWithNestedSetTimeout();
});
User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement