setTimeout / clearTimeout problems

JavascriptJqueryTimerSettimeout

Javascript Problem Overview


I try to make a page to go to the startpage after eg. 10sec of inactivity (user not clicking anywhere). I use jQuery for the rest but the set/clear in my test function are pure javascript.

In my frustation I ended up with something like this function that I hoped I could call on any click on the page. The timer starts fine, but is not reset on a click. If the function is called 5 times within the first 10 seconds, then 5 alerts will apear... no clearTimeout...

function endAndStartTimer() {
    window.clearTimeout(timer);
    var timer;
    //var millisecBeforeRedirect = 10000; 
    timer = window.setTimeout(function(){alert('Hello!');},10000); 
}

Any one got some lines of code that will do the trick?

  • on any click stop, reset and start the timer.
  • When timer hits eg. 10sec do something.

Javascript Solutions


Solution 1 - Javascript

You need to declare timer outside the function. Otherwise, you get a brand new variable on each function invocation.

var timer;
function endAndStartTimer() {
  window.clearTimeout(timer);
  //var millisecBeforeRedirect = 10000; 
  timer = window.setTimeout(function(){alert('Hello!');},10000); 
}

Solution 2 - Javascript

The problem is that the timer variable is local, and its value is lost after each function call.

You need to persist it, you can put it outside the function, or if you don't want to expose the variable as global, you can store it in a closure, e.g.:

var endAndStartTimer = (function () {
  var timer; // variable persisted here
  return function () {
    window.clearTimeout(timer);
    //var millisecBeforeRedirect = 10000; 
    timer = window.setTimeout(function(){alert('Hello!');},10000); 
  };
})();

Solution 3 - Javascript

That's because timer is a local variable to your function.

Try creating it outside of the function.

Solution 4 - Javascript

A way to use this in react:

class Timeout extends Component {
  constructor(props){
    super(props)

    this.state = {
      timeout: null
    }

  }

  userTimeout(){
    const { timeout } = this.state;
    clearTimeout(timeout);
    this.setState({
      timeout: setTimeout(() => {this.callAPI()}, 250)
    })

  }
}

Helpful if you'd like to only call an API after the user has stopped typing for instance. The userTimeout function could be bound via onKeyUp to an input.

Solution 5 - Javascript

Not sure if this violates some good practice coding rule but I usually come out with this one:

if(typeof __t == 'undefined')
        __t = 0;
clearTimeout(__t);
__t = setTimeout(callback, 1000);

This prevent the need to declare the timer out of the function.

EDIT: this also don't declare a new variable at each invocation, but always recycle the same.

Hope this helps.

Solution 6 - Javascript

Practical example Using Jquery for a dropdown menu ! On mouse over on #IconLoggedinUxExternal shows div#ExternalMenuLogin and set time out to hide the div#ExternalMenuLogin

On mouse over on div#ExternalMenuLogin it cancels the timeout. On mouse out on div#ExternalMenuLogin it sets the timeout.

The point here is always to invoke clearTimeout before set the timeout, as so, avoiding double calls

var ExternalMenuLoginTO;
$('#IconLoggedinUxExternal').on('mouseover mouseenter', function () {

    clearTimeout( ExternalMenuLoginTO )
    $("#ExternalMenuLogin").show()
});

$('#IconLoggedinUxExternal').on('mouseleave mouseout', function () {

    clearTimeout( ExternalMenuLoginTO )    
    ExternalMenuLoginTO = setTimeout(
        function () {

            $("#ExternalMenuLogin").hide()

        }
        ,1000
    );
    $("#ExternalMenuLogin").show()
});

$('#ExternalMenuLogin').on('mouseover mouseenter', function () {

    clearTimeout( ExternalMenuLoginTO )
});
$('#ExternalMenuLogin').on('mouseleave mouseout', function () {
    
    clearTimeout( ExternalMenuLoginTO )
    ExternalMenuLoginTO = setTimeout(
        function () {

            $("#ExternalMenuLogin").hide()

        }
        ,500
    );
});

Solution 7 - Javascript

This works well. It's a manager I've made to handle hold events. Has events for hold, and for when you let go.

function onUserHold(element, func, hold, clearfunc) {
    //var holdTime = 0;
    var holdTimeout;

    element.addEventListener('mousedown', function(e) {
        holdTimeout = setTimeout(function() {
            func();
            clearTimeout(holdTimeout);
            holdTime = 0;
        }, hold);
        //alert('UU');
    });

    element.addEventListener('mouseup', clearTime);
    element.addEventListener('mouseout', clearTime);

    function clearTime() {
        clearTimeout(holdTimeout);
        holdTime = 0;
        if(clearfunc) {
            clearfunc();
        }
    }
}

The element parameter is the one which you hold. The func parameter fires when it holds for a number of milliseconds specified by the parameter hold. The clearfunc param is optional and if it is given, it will get fired if the user lets go or leaves the element. You can also do some work-arounds to get the features you want. Enjoy! :)

Solution 8 - Javascript

<!DOCTYPE html>
<html>

<body>

  <h2>EJEMPLO CONOMETRO CANCELABLE</h2>

  <button onclick="inicioStart()">INICIO</button>
  <input type="text" id="demostracion">
  <button onclick="finStop()">FIN</button>

  <script>
    let cuenta = 0;
    let temporalTiempo;
    let statusTime = false;


    function cronometro() {
      document.getElementById("demostracion").value = cuenta;
      cuenta++;
      temporalTiempo = setTimeout(cronometro, 500);
    }

    function inicioStart() {
      if (!Boolean(statusTime)) {
        statusTime = true;
        cronometro();
      }
    }

    function finStop() {
      clearTimeout(temporalTiempo);
      statusTime = false;

    }
  </script>

</body>

</html>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTillebeckView Question on Stackoverflow
Solution 1 - JavascriptPointyView Answer on Stackoverflow
Solution 2 - JavascriptChristian C. SalvadóView Answer on Stackoverflow
Solution 3 - JavascriptarclightView Answer on Stackoverflow
Solution 4 - Javascriptzero_coolView Answer on Stackoverflow
Solution 5 - JavascriptclamiaxView Answer on Stackoverflow
Solution 6 - JavascriptDiego FaveroView Answer on Stackoverflow
Solution 7 - JavascriptKino BacaltosView Answer on Stackoverflow
Solution 8 - JavascriptESPView Answer on Stackoverflow