执行当前的ajax调用并中止所有以前的调用

时间:2014-08-29 23:13:16

标签: javascript jquery ajax

我正在尝试构建一个自动完成的UI。有一个输入,其keyup函数对服务器执行ajax调用以获取最相关的数据。但是如果用户键入一个单词,比如10个字符长,那么每个keyup进行一次ajax调用,并且我的对话框刷新10次。

我尝试使用abort()进行ajax调用。当我对之前的ajax呼叫进行中止时,没有进行呼叫但是在执行最后一次呼叫之前它仍然等待10次呼叫,这使得用户体验非常糟糕。

那么有没有办法只执行当前的ajax调用而没有任何延迟?

我的代码的一部分:

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

4 个答案:

答案 0 :(得分:1)

OP,这有两个部分。第一个是你的中止,似乎你已经拥有了。

第二是在这个过程中引入宽恕。您希望在用户停止键入时触发,而不是在每次按键时触发。

您需要同时使用keyUp和keyDown。在keyUp上,设置超时以触发提交。给它大概700ms。在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);

      });
    });

这样做会在每次按键启动时不断设置超时,但每次按键关闭时都会取消该超时。这将导致您的服务调用从触发开始直到用户停止输入或暂停时间过长为止。最终结果是,您将最终中止一小部分通话。

答案 1 :(得分: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 ajax调用时键入samp时需要键入p。当用户输入le时,没有任何事情发生!

如果您使用jquery Autocomplete 你可以用

minLenght这样您就可以检查文本框的当前lenght,当用户输入至少3个字符时,您必须调用ajax请求。

delay(在最后一次击键和ajax通话之间。通常2-300ms应该这样做)

并使用AjaxQueue

在快速搜索此问题后,我发现此link显示了另一种方法,可以通过使用缓存来防止多个ajax调用自动完成

答案 2 :(得分:0)

您可以使用globalTimeoutsetTimeout()重置的clearTimeout()变量。

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

这样,只要您的客户端推送keydown,就会清除超时,但只要客户发布密钥onkeyup,就会再次设置超时,因此$.ajax()只会在这种情况下,在10毫秒之后,如果没有关键动作则调用。我承认这不会阻止已经发出的$.ajax()来电,但是它可能会因为发生得非常快而无所谓,并且因为此示例会阻止将来的$.ajax()来电只要客户不断输入。

答案 3 :(得分: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/