Problèmes de setTimeout / clearTimeout

103

J'essaye de faire une page pour aller à la page de départ après par exemple. 10 secondes d'inactivité (l'utilisateur ne clique nulle part). J'utilise jQuery pour le reste mais le set / clear dans ma fonction de test est pur javascript.

Dans ma frustation, je me suis retrouvé avec quelque chose comme cette fonction que j'espérais pouvoir appeler à n'importe quel clic sur la page. Le minuteur démarre correctement, mais n'est pas réinitialisé en un clic. Si la fonction est appelée 5 fois dans les 10 premières secondes, alors 5 alertes apparaîtront ... no clearTimeout ...

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

Quelqu'un a des lignes de code qui feront l'affaire? - à tout clic, arrêtez, réinitialisez et démarrez le chronomètre. - Lorsque la minuterie frappe, par exemple. 10sec faire quelque chose.

Tillebeck
la source

Réponses:

226

Vous devez déclarer en timer dehors de la fonction. Sinon, vous obtenez une toute nouvelle variable à chaque appel de fonction.

var timer;
function endAndStartTimer() {
  window.clearTimeout(timer);
  //var millisecBeforeRedirect = 10000; 
  timer = window.setTimeout(function(){alert('Hello!');},10000); 
}
Pointu
la source
plus 1 car il faut, dans ce cas, effacer la variable qui masque le timeOut avant d'appeler le time out, ainsi, en évitant de l'invoquer deux fois
Diego Favero
46

Le problème est que la timervariable est locale et que sa valeur est perdue après chaque appel de fonction.

Vous devez le conserver, vous pouvez le mettre en dehors de la fonction, ou si vous ne voulez pas exposer la variable comme globale, vous pouvez la stocker dans une fermeture , par exemple:

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

C'est parce que la minuterie est une variable locale de votre fonction.

Essayez de le créer en dehors de la fonction.

arc-en-ciel
la source
6

Une façon d'utiliser ceci dans 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)
    })

  }
}

Utile si vous souhaitez appeler une API uniquement après que l'utilisateur a cessé de taper par exemple. La fonction userTimeout peut être liée via onKeyUp à une entrée.

zero_cool
la source
1
C'est ce que je cherchais depuis quelques heures, merci. Je me demandais juste s'il y avait une meilleure façon pour que ce genre de résultat se produise?
Nikasv
1
@nikasv throttling et debouncing sont deux alternatives: medium.com/@_jh3y/…
zero_cool
2

Je ne sais pas si cela enfreint une règle de codage de bonne pratique, mais je viens généralement avec celle-ci:

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

Cela évite de devoir déclarer le temporisateur hors de la fonction.

EDIT: cela ne déclare pas non plus une nouvelle variable à chaque invocation, mais recycle toujours la même chose.

J'espère que cela t'aides.

clamiax
la source
0

Cela fonctionne bien. C'est un gestionnaire que j'ai fait pour gérer les événements de mise en attente. A des événements pour tenir, et pour quand vous lâchez prise.

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();
        }
    }
}

Le paramètre d'élément est celui que vous détenez. Le paramètre func se déclenche lorsqu'il est maintenu pendant un nombre de millisecondes spécifié par le paramètre hold. Le paramètre clearfunc est facultatif et s'il est donné, il sera déclenché si l'utilisateur lâche ou quitte l'élément. Vous pouvez également effectuer quelques solutions pour obtenir les fonctionnalités souhaitées. Prendre plaisir! :)

Kino Bacaltos
la source
0

Exemple pratique Utilisation de Jquery pour un menu déroulant! Lorsque vous passez la souris sur #IconLoggedinUxExternal, affiche la div # ExternalMenuLogin et définit le délai d'attente pour masquer la div # ExternalMenuLogin

Lorsque vous passez la souris sur div # ExternalMenuLogin, le délai d'expiration est annulé. Lors de la souris sur div # ExternalMenuLogin, il définit le délai d'expiration.

Le point ici est toujours d'appeler clearTimeout avant de définir le délai d'expiration, afin d'éviter les doubles appels

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
    );
});
Diego Favero
la source