2010-03-09 5 views
29

Wie kann ich Aktionen zwischen Tastendruck in jQuery verzögern. Zum Beispiel;Verzögerung von Aktionen zwischen Tastendruck in jQuery

Ich habe so etwas wie diese

if($(this).val().length > 1){ 
    $.post("stuff.php", {nStr: "" + $(this).val() + ""}, function(data){ 
    if(data.length > 0) { 
     $('#suggestions').show(); 
     $('#autoSuggestionsList').html(data); 
    }else{ 
     $('#suggestions').hide(); 
    } 
}); 
} 

ich Entsendung Daten verhindern will, wenn der Benutzer kontinuierlich eingeben. Also, wie kann ich 0,5 Sekunden Verzögerung geben?

+0

Ich gehe davon aus, dass dies in einer Funktion, die in 'keypress()' übergeben wird? – Jeremy

Antwort

59

Sie können jQuery Daten Fähigkeiten verwenden, um dies etwas zu tun,:

$('#mySearch').keyup(function() { 
    clearTimeout($.data(this, 'timer')); 
    var wait = setTimeout(search, 500); 
    $(this).data('timer', wait); 
}); 

function search() { 
    $.post("stuff.php", {nStr: "" + $('#mySearch').val() + ""}, function(data){ 
    if(data.length > 0) { 
     $('#suggestions').show(); 
     $('#autoSuggestionsList').html(data); 
    }else{ 
     $('#suggestions').hide(); 
    } 
    }); 
} 

Der Hauptvorteil ist hier keine globalen Variablen alle über den Platz, und man kann dies in einer anonymen Funktion in der setTimeout wickelt wenn Sie wollten, versuchen Sie einfach, das Beispiel so sauber wie möglich zu machen.

10

Alles, was Sie tun müssen, ist Ihre Funktion in einem Timeout wickeln, die zurückgesetzt wird, wenn der Benutzer eine Taste drückt:

var ref; 
var myfunc = function(){ 
    ref = null; 
    //your code goes here 
}; 
var wrapper = function(){ 
    window.clearTimeout(ref); 
    ref = window.setTimeout(myfunc, 500); 
} 

Dann einfach „Wrapper“ in Ihrem Schlüsselereignis aufzurufen.

+0

+1 weniger jQuery für eine einfache Lösung. – A1rPun

1

Ich würde wickeln Sie es in einer Funktion wie so:

var needsDelay = false; 

    function getSuggestions(var search) 
    { 
    if(!needsDelay) 
    { 
     needsDelay = true; 
     setTimeout("needsDelay = false", 500); 

     if($(this).val().length > 1){ 
      $.post("stuff.php", {nStr: "" + search + ""}, function(data){ 
       if(data.length > 0) { 
        $('#suggestions').show(); 
        $('#autoSuggestionsList').html(data); 
       }else{ 
        $('#suggestions').hide(); 
       } 
      }); 
     } 
    } 


    } 

Auf diese Weise, egal, wie oft Sie diesen ping, werden Sie nie als alle 500 Millisekunden mehr suchen.

+5

übergebe niemals eine Zeichenkette an setTimeout! eval ist böse (in den meisten Fällen) :) verwende eine anonyme Funktion wie: 'setTimeout (function() {needsDelay = false;}, 500);' stattdessen. –

+0

Ich weiß, dass Eval ist böse, aber ich bin immer noch faul und setzen Eval-Anweisungen in meinem Code. Ich muss das zu meiner Nazi-Liste hinzufügen. Nicht mehr eval. – thaBadDawg

3

Es gibt ein nettes Plugin, um damit umzugehen. jQuery Throttle/Debounce

+0

gibt es keine jQuery-Abhängigkeit für alles? Ich muss zugeben - der Name "Debounce" ruft zynisches Gelächter hervor! Wie auch immer, guter Fund. – matrixugly

+0

lodash hat auch [Drosselung] (https://lodash.com/docs#throttle) und [debounce] (https://lodash.com/docs#debounce) Methoden –

2

Nick Antwort ist perfekt, aber wenn sofort erste Event-Handling entscheidend ist, dann denke ich, dass wir tun können:

$(selector).keyup(function(e){ //or another event 

    if($(this).val().length > 1){ 
     if !($.data(this, 'bouncing-locked')) { 

      $.data(this, 'bouncing-locked', true) 

      $.post("stuff.php", {nStr: "" + $(this).val() + ""}, function(data){ 
       if(data.length > 0) { 
        $('#suggestions').show(); 
        $('#autoSuggestionsList').html(data); 
       }else{ 
        $('#suggestions').hide(); 
       } 
      }); 

      self = this 
      setTimeout(function() { 
       $.data(self, 'bouncing-locked', false); 

       //in case the last event matters, be sure not to miss it 
       $(this).trigger("keyup"); // call again the source event 
      }, 500) 
     } 
    } 
});