Когда у меня есть обратный вызов, который может быть запущен несколько раз, но я хочу использовать только последний, я использую этот шаблон:
var resultsXHR, resultsTimer, resultsId=0;
$('input').keyup(function(){
clearTimeout(resultsTimer); // Remove any queued request
if (resultsXHR) resultsXHR.abort(); // Cancel request in progress
resultsTimer = setTimeout(function(){ // Record the queued request
var id = ++resultsId; // Record the calling order
resultsXHR = $.get('/results',function(data){ // Capture request in progress
resultsXHR = null; // This request is done
if (id!=resultsId) return; // A later request is pending
// ... actually do stuff here ...
});
},500); // Wait 500ms after keyup
});
Одного abort()
недостаточно, чтобы предотвратить успешный обратный вызов; вы все равно можете обнаружить, что ваш обратный вызов запущен, даже если вы пытались отменить запрос. Вот почему необходимо использовать трекер resultsId
и сделать так, чтобы ваш обратный вызов прекратил обработку, если другой, более поздний перекрывающийся обратный вызов готов к работе.
Учитывая, насколько это распространено и обременительно, я думаю, что это хорошая идея, чтобы обернуть его в многократное использование, не требуя, чтобы вы придумывали уникальный триплет имен локальных переменных для каждого, который вы хотите обработать :
(function($){
$.fn.bindDelayedGet = function(event,delay,url,dataCallback,dataType,callback){
var xhr, timer, ct=0;
return this.bind(event,function(){
clearTimeout(timer);
if (xhr) xhr.abort();
timer = setTimeout(function(){
var id = ++ct;
xhr = $.get(url,dataCallback && dataCallback(),function(data){
xhr = null;
if (id==ct) callback(data);
},dataType);
},delay);
});
};
})(jQuery);
// In action
var inp = $('#myinput').bindDelayedGet('keyup',400,'/search',
function(){ return {term:inp.val()}; },
'html',
function(html){ $('#searchResults').clear().append(html); }
);
Вы можете найти вышеуказанный код более подробно на моем сайте .