使用Jquery .ajax取消正在进行的AJAX请求?

39

可能是重复问题:
使用jQuery使用JavaScript终止Ajax请求

这是我正在使用的简单代码:

$("#friend_search").keyup(function() {

    if($(this).val().length > 0) {
        obtainFriendlist($(this).val());
    } else {
        obtainFriendlist("");
    }

});

function obtainFriendlist(strseg) {

    $.ajax({
       type: "GET",
       url: "getFriendlist.php",
       data: "search="+strseg,
       success: function(msg){
        UIDisplayFriends(msg);
       }
     });
}

基本上,如果在函数 obtainFriendlist 返回结果之前(并触发 UIDisplayFriends(msg)),出现了 keyup 事件,我需要取消正在进行的请求。我一直遇到的问题是它们会累积,然后突然触发多次UIDisplayFriends 函数。

非常感谢,建议也很有帮助。

2个回答

24
< p > $.ajax 的返回值是一个 XHR 对象,您可以在其上调用操作。要中止该函数,您可以执行以下操作:

var xhr = $.ajax(...)
...
xhr.abort()

同时加入防抖动机制可能会更好,以减轻服务器的负担。以下代码只有在用户停止输入100毫秒后才会发送XHR请求。

var delay = 100,
    handle = null;

$("#friend_search").keyup(function() {
    var that = this;
    clearTimeout(handle);
    handle = setTimeout(function() {
        if($(that).val().length > 0) {
            obtainFriendlist($(that).val());
        } else {
            obtainFriendlist("");
        }
    }, delay);
});

第三件你应该做的事情是根据请求是否仍然有效来过滤XHR响应:

var lastXHR, lastStrseg;

function obtainFriendlist(strseg) {
    // Kill the last XHR request if it still exists.
    lastXHR && lastXHR.abort && lastXHR.abort();

    lastStrseg = strseg;
    lastXHR = $.ajax({
       type: "GET",
       url: "getFriendlist.php",
       data: "search="+strseg,
       success: function(msg){

        // Only display friends if the search is the last search.
        if(lastStrseg == strseg) 
          UIDisplayFriends(msg);
       }
     });
}

1
我喜欢你对延迟的处理方式,很不错。但是,如果用户输入速度较慢,是否仍存在请求堆积的风险,从而在每次按键时触发新的ajax请求? - Christofer Eliasson
1
这仍然是一种风险,所以您需要同时应用两种策略,即取消旧查询和上述减少服务器调用的方法。第三个屏幕将验证输出是否仍然与请求匹配。 - Brian Nickel
1
非常好。谢谢,这很有启发性。 - TaylorMac

0

你可以使用一个变量,比如isLoading,在使用.ajax的beforeSend(jqXHR, settings)选项时将其设置为true,然后使用complete设置将变量重新设置为false。这样,在触发另一个ajax调用之前,你只需要根据该变量进行验证即可。

var isLoading = false;
$("#friend_search").keyup(function() {

    if (!isLoading) {
       if($(this).val().length > 0) {
           obtainFriendlist($(this).val());
       } else {
           obtainFriendlist("");
       }
    }

});

function obtainFriendlist(strseg) {

    $.ajax({
       type: "GET",
       url: "getFriendlist.php",
       beforeSend: function () { isLoading = true; },
       data: "search="+strseg,
       success: function(msg){
        UIDisplayFriends(msg);
       },
       complete: function() { isLoading = false; }
     });
}

1
这不应该是相反的吗?如果用户在XHR返回之前键入了“TEST”,那么E、S和T的按键将被忽略,服务器响应仅为“T”。 - Brian Nickel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接