Jack Hales
Jack Hales

Reputation: 1644

What's the easiest way to stop a function from being called every X seconds in JavaScript?

I've looked around for a soundproof solution to my problem but was not able to find many SO questions like this.

My move function gets called each click on a tile, I want to block the user from moving whilst they are currently in motion to block overlapping execution bugs.

The functions work as following:

move: function(steps){
    for (var stepx in steps) {
      window.setTimeout(. . ., 300 * stepx);
    }
}

Which iterates, adding a forward 300ms to when the function is going to be called each time. If it's 5 steps, it'll finish after 1.5 seconds.

But, when the user clicks twice it sets up a parallel bunch of handlers that glitch the user from two areas: the original path being travelled and the secondary.

Is there a way to block execution or queue the timeouts?

Upvotes: 0

Views: 472

Answers (2)

Chris Barr
Chris Barr

Reputation: 33972

You just need to save the timeout to a variable and call clearTimeout() - however, your example creates multiple timeouts in a loop, so you'd need to save them all and then stop them all. It could be done like this:

var timers = [];
var running = false;

function makeSteps(steps) {
  if (!running) {
    running = true;
    for (var i = 0; i <= steps; i++) {
      timers.push(setTimeout(function() {
        console.log("Step");
      }, 300 * i));
    }
  }
}

function stopAllSteps() {
  for (var i = 0; i <= timers.length; i++) {
    clearTimeout(timers[i]);
  }
  running = false;
  console.log("stopped!");
}
<button type="button" onclick="makeSteps(100)">Start</button>
<button type="button" onclick="stopAllSteps()">Stop</button>

Upvotes: 1

Orelsanpls
Orelsanpls

Reputation: 23495

You could use of a variable to block the user clicks until it gets done.

If I understood well what you asked for.

let inProgress = false;

function clickFunc(steps) {
  console.log('The user clicked');

  if (inProgress) {
    console.log('Action already in progress');

    return;
  }

  inProgress = true;

  for (let i = 0; i < steps; i += 1) {
    window.setTimeout(() => {
      // if the last step is over, we stop the click block
      if (i === steps - 1) {
        inProgress = false;
      }

      console.log('One step done');
    }, 300 * i);
  }
}
.button {
  height: 2em;
  width: 10em;
  background-color: #444444;
  color: white;
  cursor: pointer;
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;
}

.button:hover {
  opacity: 0.9;
}
<div class="button" onclick="clickFunc(3)">Button</div>

Upvotes: 0

Related Questions