Display loading spinner if function takes longer than X milliseconds

Viewed 1279

I would like to display a loading spinner but ONLY if "my_code_here" takes longer than X milliseconds to execute.

I have managed to do this:

<button onClick='my_long_function()'></button>
<div class="spinner" style="display: none;"></div>
my_long_function: function()
{
    $(".spinner").show(200, function()
    {
        my_code_here
        my_code_here
        my_code_here

        $(".spinner").hide();
    }
}

It works but it shows the spinner even when the code takes less than 100ms, so it's showing up during the blink of an eye and I have issues making that look good.

Note that it's not ajax waiting for a server answer, it's all client side.

I tried stuff with setTimeout and clearTimeOut by reading like 5 stackoverflow questions but either it doesn't seem to trigger or the spinner stays forever.

1 Answers

https://jsfiddle.net/w9khvx50/1/

const loader = document.querySelector('.loader');
const status = document.querySelector('.status');

// This function simply emulates an asynchronous function
const wait = (ms = 5000) => {
    return new Promise((resolve) => {
    setTimeout(() => {
        resolve();
    },ms)
  })
}

const toggleLoader = (state) => {
    loader.classList.toggle('show', state);
}


const timeout = setTimeout(toggleLoader, 2000);

status.textContent = "Starting load function";
wait(4000)
.then(() => {
    status.textContent = "Load function complete";
    toggleLoader(false);
        clearTimeout(timeout);
})
.loader {
  border: 16px solid #f3f3f3;
  border-radius: 50%;
  border-top: 16px solid #3498db;
  width: 120px;
  height: 120px;
  animation: spin 2s linear infinite;
  opacity: 0;
}

.loader.show {
  opacity: 1;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}
<div>
  <div class="loader"></div>
  <div class="status"></div>
</div>

The best way here is the cleared timeout, I think you must have been implementing it wrongly before. If the ms in const timeout is less than the wait time, the loader will show.

Note that if the function you're executing is not asynchronous, then you'll need to investigate Web Workers, since your function will block the main thread and nothing else will execute (such as running a timeout callback). You should create a web worker, delegate your long function to it, and then clear the timeout if you receive a complete message before the time is up.

Related