2014-08-29 53 views
1

我正在尝试构建一个自动完成的用户界面。有一个输入,其keyup函数执行ajax调用服务器以获取最相关的数据。但是,如果用户键入一个字,例如10个字符,则每个keyup都会发出一个ajax调用,并且我的对话框将刷新10次。执行当前的ajax调用并中止所有先前的调用

我尝试使用abort()进行ajax调用。当我对之前的ajax调用进行中止时,不会进行调用,但仍然会在执行最后一个调用之前等待10个调用,这会使用户体验非常糟糕。

那么有没有一种方法可以执行当前的ajax调用,而不会从前一个延迟?

我的代码的一部分:

var request_autocomplete=jQuery.ajax({}); 
$('.review_autocomplete').keyup(function() { 
    request_autocomplete.abort(); 
    request_autocomplete=jQuery.ajax({ 
     // DO something 
    }); 
}); 
+0

可能重复[jQuery的自动完成,可以给我时,我提出一个新的前一个AJAX调用停止?](http://stackoverflow.com/questions/4121963/jquery-autocomplete-can-i-have-the-previous-ajax-calling-stopped-when-i-raise -a) – Farshad 2014-08-29 23:51:30

+0

我不使用JQuery自动完成 – 2014-08-30 00:18:45

回答

1

OP,这有两个部分。第一个是你的放弃,看起来你已经拥有了。

第二个是在过程中引入宽恕。你想在用户停止输入时触发,而不是每次按键。

您需要同时使用keyUp和keyDown。在keyUp上,设置一个超时来激发你的提交。给它也许700毫秒。在KeyDown上,清除超时。

var request_autocomplete=jQuery.ajax({}); 
    var forgiveness; 

    // first your AJAX routine as a function 
    var myServiceCall = function() { 
     request_autocomplete.abort(); 
     request_autocomplete=jQuery.ajax({ 
      // DO something 
    } 

    // keyup 
    $('.review_autocomplete').keyup(function() { 
     forgiveness = window.setTimeout(myServiceCall, 700); 

     }); 
    }); 

    // key down 
    $('.review_autocomplete').keydown(function() { 
     window.clearTimeout(forgiveness); 

     }); 
    }); 

这将完成在不断设置超时火每次关键是,但每次一键被按下,这将取消暂停。这会使您的服务电话不会触发,直到用户停止键入或暂停太久。最终的结果是,你会结束一个很小的百分比的电话。

+0

你可以用一些相关的代码来解释这个吗 – 2014-08-29 23:45:12

+1

是的 - 我会编辑和添加。 – 2014-08-29 23:45:54

0

你可以实现你在你的问题问的方式如下预防例如3个电话:

var calls = 0; 
$('.review_autocomplete').keyup(function() { 
    if (calls >3) { 
     request_autocomplete.abort(); 
     request_autocomplete=jQuery.ajax({ 
      // DO something 
     }); 
     calls = 0; 
    } 
    calls++; 
}); 

但这种方式不推荐,因为当用户想要输入sample,而用户输入samp则输入p ajax调用起来。并且当用户类型le什么也没有发生!

如果您正在使用jquery​​3210 您可以使用

minLenght,所以你可以检查文本框的当前lenght,当用户键入至少3个字符,则必须调用Ajax请求。

delay(最后一次按键和Ajax调用之间。通常2-300ms应该做的)

和有关此问题的快速搜索后使用AjaxQueue

我发现这个link显示的另一种方式,以防止多个ajax呼吁通过使用高速缓存自动完成

+0

这不会工作我猜是因为用户的打字速度将会比从服务器获取时间更快。因此,它会导致我所有的请求超时 – 2014-08-29 23:16:31

+0

我认为这个问题是重复的[http://stackoverflow.com/questions/4121963/jquery-autocomplete-can-i-have-the-previous-ajax-calling-停时,我加注-A(http://stackoverflow.com/questions/4121963/jquery-autocomplete-can-i-have-the-previous-ajax-calling-stopped-when-i-raise-a ) – Farshad 2014-08-29 23:51:01

0

您可以使用globalTimeout变量,使用setTimeout()clearTimeout()重置。

var globalTimeout; 
$('.review_autocomplete').keydown(function(){ 
    if(globalTimeout)clearTimeout(globalTimeout); 
}).keyup(function(){ 
    globalTimeout = setTimeoout(function(){ 
    $.ajax({/* you know the drill */}); 
    }, 10); 
}); 

这样的超时被清除,只要您的客户端推送​​,但因为你的客户端释放的关键onkeyup,因此如果没有按键动作$.ajax()只会叫暂停重新一旦设置后,在这种情况下为10毫秒。我承认,这不会阻止已经完成的$.ajax()呼叫,但它可能无关紧要,因为它们发生的速度非常快,并且只要客户端继续键入,此示例就会阻止将来的$.ajax()呼叫。

0

尝试

var count = { 
    "start": 0, 
    // future , by margin of `count.timeout` 
    "complete": 0, 
    // if no `keyup` events occur , 
    // within span of `count.timeout` 
    // `request_autocomplete()` is called 
    // approximately `2` seconds , below , 
    // adjustable 
    "timeout" : 2 
}; 
$('.review_autocomplete') 
.focus() 
.on("keyup", function (e) { 
    elem = $(this); 
    window.clearInterval(window.s); 
    window.s = null; 
    var time = function() { 
     var t = Math.round($.now()/1000); 
     count.start = t; 
     count.complete = t + count.timeout; 
    }; 
    time(); 
    var request_autocomplete = function() { 

     return jQuery.ajax({ 
      url: "/echo/json/", 
      type: "POST", 
      dataType: "json", 
      data: { 
       json: JSON.stringify({ 
        "data": elem.val() 
       }) 
      } 
      // DO something 
     }).done(function (data) { 
      window.clearInterval(s); 
      console.log("request complete", data); 
      $("body").append("<br /><em>" + data.data + "</em>"); 
      elem.val(""); 
      count.start = count.complete = 0; 
      console.log(count.start, count.complete); 
     }); 
    }; 
    window.s = setInterval(function() { 
     if (Math.round($.now()/1000) > count.complete) { 
      request_autocomplete(); 
      console.log("requesting data"); 
     }; 
    // increased to `1000` from `501` 
    }, 1000); 

}); 

的jsfiddle http://jsfiddle.net/guest271314/73yrndwy/

相关问题