Jquery ajax请求,等待最新请求完成

8
我有一个文本框,每当用户输入一个字母时,我都会通过ajax请求进行搜索,并将结果实时显示给用户。通常情况下,当用户键入字母时,请求的时间比用户输入新字母的时间更长,因此在第一个请求结束之前就会发出新的请求。如果第一个请求能够结束后再进行下一个请求,那将会更好。是否有一种好的方法可以只在最新的请求结束后才发出新的请求?
这是我的jquery代码:
$("#MyTextBox").change(function() {
    if (this.value.length > 2) {
        $.ajax({
            type: "GET",
            url: "http://www.domain.com/Service.svc/Search?keyword=" + this.value,
            dataType: "json",
            success: function(data) {
                //here I have some code that shows the result for the user
            }
        });
    }
});
5个回答

12
您可以创建一个布尔变量,根据是否已经有请求正在进行,它将保留true或false。在开始请求时将其设置为true,在回调函数中将其设置回false。
var request_in_process = false;
$("#MyTextBox").change(function() {
    if (this.value.length > 2 && !request_in_process) {
        request_in_process = true;
        $.ajax({
            type: "GET",
            url: "http://www.domain.com/Service.svc/Search?keyword=" + this.value,
            dataType: "json",
            success: function(data) {
                request_in_process = false;
                //here I have some code that shows the result for the user
            }
        });
    }
});

谢谢!这正是我要找的。但由于某种原因,当我输入文本时,似乎每次输入一个字母都会有一些小问题,每个字母都会出现一些延迟。Ajax请求应该是异步发送的,所以它不应该影响文本框,对吧? - Martin
1
最好将带有清理代码的函数分配给complete设置中的request_in_progress,而不是在请求失败时分配给success - David Neale

8

您可以中止 AJAX 请求。将请求跟踪为变量,并在重新初始化请求之前中止它。

var request = $.ajax({ ... });
request.abort();

这样做的额外好处是对用户输入更加响应。如果用户在第一次请求被发起后输入了更多内容,他可能已经不再关心第一组结果了。中止并重新创建AJAX请求意味着用户将获得更好的结果集。


0

正如ceejayoz所提到的,您应该中止之前的请求。(如果用户无法按照他们想要的方式输入,则等待请求会使用户感到疯狂。而且,更喜欢旧请求而不是新请求会使结果过时。)那么怎么样:

var request = null;
//...       
$("#MyTextBox").change(function() {
    if (this.value.length > 2) {
        if (request && request.abort)
            request.abort();
        request = $.ajax({
            type: "GET",
            url: "http://www.domain.com/Service.svc/Search?keyword=" + this.value,
            dataType: "json",
            success: function(data) {
            //here I have some code that shows the result for the user
            request = null;                
        });
    }             
});

0
这是一个稍微更加健壮的实现。基本上,我们将 ajax 对象(即 promise 对象)保存在闭包中,以便后续调用可以查看它。如果下一个调用发现请求的状态仍在等待中,则会向该挂起请求添加回调,而不是生成新的请求。jQuery 将按照它们添加的相同顺序触发所有回调。但是,同一个调用者可能一遍又一遍地尝试创建请求。为了防止这种情况,我添加了 callerId 参数。如果在前一个请求仍处于挂起状态时,同一调用者再次发出请求,则我们将忽略该请求。为了完整起见,我还添加了 cachedValues。因此,如果已经进行了 ajax 请求,我们就不会再次进行。
var ajaxRequestor = function ($) {
    "use strict";

    //privates
    var cahedValues = {};
    var currentAjaxRequest, callers;

    //public interface
    return {
        getData: function (callerId, onGet, onFail, forceRefresh) {
            if (forceRefresh || !cahedValues.myData) {

                //If there is a pending request, don't start new one
                if (!currentAjaxRequest || currentAjaxRequest.state() != "pending") {
                    currentAjaxRequest = $.getJSON("data/MyData.json");
                    callers = {};   //list of callers waiting for request
                }

                //if this caller is not in the list, add it and queue up its callbacks to existing request
                if (!callers[callerId]) {   
                    callers.callerId = callerId;

                    currentAjaxRequest.done(function (data, textStatus) {
                        cahedValues.myData = data;
                        onGet(data);
                    });

                    currentAjaxRequest.fail(function (jqxhr, textStatus, error) {
                        if (!!onFail) {
                            onFail(error);
                        }
                        else throw error;
                    });
                }
            }
            else {
                onGet(cahedValues.myData);
            }
        },

        invalidateMyData: function () {
            delete cahedValues.myData;
        }
    };
})($);

0

您可以利用ajaxComplete,以便在发起新请求之前知道请求何时完成。

您可以将其与bind/unbind结合使用,以便手动添加一次更改事件,然后在ajax请求开始时解除绑定,在ajax请求完成时重新绑定。


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