JavaScript: Continuously change character

Viewed 90

I have a <p> tag

<p id="rev">|</p>

that I want to continuously change via Javascript to create an old-school loading animation that would follow this pattern in repetition:

| / - \

I'm not familiar with how Javascript treats recursion, but the following block of code simply creates a long loading period and doesn't function as intended:

function runRev() {
    document.getElementById('rev').innerHTML = "/";
    setTimeout(function(){}, 2000);
    document.getElementById('rev').innerHTML = "-";
    setTimeout(function(){}, 2000);
    document.getElementById('rev').innerHTML = "\\";
    setTimeout(function(){}, 2000);
    document.getElementById('rev').innerHTML = "|";
    setTimeout(function(){}, 2000);
    runRev();
}
runRev();

I imagine there is a better way to accomplish this. How can I create a Javascript function that continuously runs to change that single character?

3 Answers

This really doesn't require recursion. Just using setInterval() while looping over a character array will do:

const chars = ['|', '/', '-', '\\'];
const el = document.getElementById('loading');
let i = 0;

setInterval(() => {
  el.innerHTML = chars[i];
  i = (i + 1) % chars.length;
}, 100);
<span id="loading"></span>

A recursion way may looks like this:

const chars = ['|', '/', '-', '\']
const element = document.getElementById('rev')
function run (count) {
  element.innerHTML = chars[count % chars.length]
  return setTimeout(() => run(count + 1), 2000)
}
run(0)

If your browser supports async/await:

const chars = ['|', '/', '-', '\']
const element = document.getElementById('rev')

async function run (count) {
  element.innerHTML = chars[count % chars.length]
  await sleep(2000)
  run(step + 1)
}
run(0)

function sleep (duration) {
  return new Promise((resolve) => setTimeout(resolve, duration))
}



You could use css animation to do this.

@keyframes spinner {
    0% {
        content: "|";
    }
    30% {
        content: "/";
    }
    50% {
        content: "-";
    }
    100% {
        content: "\\";
    }
}

.element::after {
    animation: spinner 0.5s linear infinite;
    display: block;
    font-size: 20px;
    content: "|";
}
<p class="element"></p>

Related