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.

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

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

15

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

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


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.


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.


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! :)


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
    );
});
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.