2010-04-19 3 views
3

Je voudrais construire une fonction qui retourne false si elle a été appelée il y a moins d'une demi-seconde.Fonction Javascript: Une demi-seconde s'est-elle écoulée depuis la dernière fois que vous avez essayé?

timething.timechill=function(){ 
    var last 
    if (last){ 
      if ((now.getTime()-last)>500){ 
        return true 
      } 
      else{ 

        return true 
      } 
    } 
    else { 
      last=now.getTime() 
      return false 
    }} 

Des idées? Je voudrais éviter setTimeout() et ignorer l'entrée si elle vient trop vite pour éviter le débordement. Est-ce une bonne pratique?

+3

Si c'est un copier coller de votre code, je vous conseille de ne pas oublier de mettre le ';' sur votre vrai code – fmsf

+0

Merci pour toutes les bonnes réponses! Je serai un meilleur programmeur js quand je l'aurai enveloppé dans ma tête. La première fois que j'utilise ce site en passant. – heorling

Répondre

5
timething.timechill = (function() { 
    var lastCall = 0; 
    return function() { 
     if (new Date() - lastCall < 500) 
      return false; 
     lastCall = new Date(); 
     //do stuff 
    } 
})(); 

L'idée ici est que (function() { ... })(); va créer une fonction anonyme et l'exécuter immédiatement. timething.timechill n'a pas cette fonction. Au lieu de cela, la fonction interne affectée a renvoyé par cette fonction.

Notez que lastCall n'est pas déclaré (en utilisant le mot-clé var) dans cette fonction interne. Et quand la fonction externe revient, lastCall ne disparaît pas parce que la fonction interne l'a "fermée" en vertu du fait qu'elle fait référence à la variable. Lorsque vous exécutez timething.timechill plus tard et qu'il rencontre cette variable, il va rechercher en dehors de la portée de la fonction pour la variable et trouver celle qui a été déclarée plus tôt. Quand elle revient, la variable ne disparaît toujours pas, puisqu'elle a été déclarée en dehors de la portée de la fonction.

Il est difficile d'expliquer ce concept clairement, mais il est très utile car lastCall est invisible pour le reste de votre code qui n'a pas besoin de le voir.

+1

Merci! J'ai fini par utiliser votre code avec une modification mineure. J'ai inséré cette autre instruction: else {lastCall = new Date(); retourner vrai; } – heorling

+0

La question est, l'appel Date() causera des problèmes plus tard? Il n'est appelé que dans des cas spéciaux. Kgiannakakis est-il exact? SetTimeout est-il le moyen de résoudre ce problème? – heorling

+0

'setTimeout' est généralement meilleur que l'interrogation. Mais si vous faites déjà des sondages, je ne pense pas que cela entraînera des problèmes supplémentaires. Il pourrait être légèrement optimisé avec 'var current = new Date();' avant l'instruction if, puis en utilisant le même 'current' pour la comparaison et l'affectation au lieu de créer deux objets' Date'. Firefox a une méthode 'Date.now()' statique qui ne crée vraisemblablement pas un objet entier, mais vous aurez besoin d'une solution de contournement pour la plupart des navigateurs. Voir https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/now –

0

Votre fonction telle que définie retournera toujours false car la variable last n'est jamais enregistrée nulle part. Vous pouvez le maintenir comme une propriété d'un objet, ou vous pouvez le maintenir dans une fermeture.

Voici un exemple de fermeture:

timething.timechill = (function() { 
    var last = 0; 

    function timechill() { 
     var now; 

     now = new Date().getTime(); 
     if (last) { 
      if (now - last > 500) { 
       // It's been long enough, allow it and reset 
       last = now; 
       return true; 
      } 
      // Not long enough 
      return false; 
     } 

     // First call 
     last = now; 
     return false; 
    } 

    return timechill; 
})()); 

qui utilise une fonction de cadrage anonyme pour construire votre fonction timechill comme une fermeture sur la variable last. La fonction de portée anonyme renvoie une référence à la fonction timechill, qui est affectée à timething.timechill. Rien d'autre que la fonction timechill peut accéder à last, c'est entièrement privé.

(je suis sûr que la logique réelle de la fonction pourrait être refactorisé un peu, mais je pense que c'est assez proche de l'original, sauf qu'il y avait un endroit où vous reveniez true où je pense que vous vouliez false.)

Que ce soit une bonne idée dépend entièrement de votre cas d'utilisation. Je ne serais pas occupé-boucle sur ce qui précède. :-) Mais si vous l'utilisez pour faire apparaître quelque chose comme "Vous ne pouvez évaluer un commentaire qu'une fois toutes les cinq secondes", ce serait bien, même si dans ce cas je le généraliserais probablement.

+0

Merci pour la réponse. J'essaie d'éviter d '"empiler" plusieurs événements de la molette de la souris et de les faire "rouler" J'ai essayé toutes les solutions ici, mais elles cassent toutes mon code pour des raisons que je me gratte la tête. A la fin vous avez "})());" que j'essaie de comprendre. Eclipse me dit "affectation invalide côté gauche" et mes tentatives pour le réparer n'ont pas fonctionné .. encore – heorling

1

Je ne pense pas que ce soit une bonne idée. Selon la façon dont vous appelez cette méthode, cela peut conduire à un comportement de "boucle infinie". Avec setTimeout vous avez un fonctionnement asynchrone - vous ne bloquez pas le navigateur, en attendant que le temps passe. La plupart des navigateurs détectent le code de blocage et désactivent votre script.

+0

Ce n'est pas bien, n'est-ce pas ... Si j'ai bien compris setTimeout, il attend simplement d'exécuter le script correctement? J'ai besoin de "l'annuler" si c'est trop tôt, pas de le retarder ... Ai-je raté quelque chose? – heorling

0

La variable "last" doit être stockée dans un autre objet, tel que l'objet window pour une variable globale ou l'objet timething ici. Et je n'ai jamais entendu parler d'un objet "maintenant" !?

timething.timechill = function(){ 

    if (!timething._last_timechill){ 

     if ((new Date())-timething._last_timechill >= 500) return true; 
     else return false; 

    } else { 

     timething._last_timechill = new Date(); 
     return false; 

    } 

} 

Vous pouvez remplacer "timething" par "window" dans la fonction si vous le souhaitez.

EDIT: Comme les autres l'ont souligné, vous pouvez également utiliser votre variable _last_timechill dans une fermeture.

Questions connexes