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

我有一个文本框,每次用户输入一个字母时,我都会使用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 } }); } }); 

您可以创建一个包含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请求。 将请求作为变量跟踪,并在重新发起请求之前中止它。

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

这具有对用户输入更敏感的附加优点。 如果用户在启动第一个请求后输入了更多内容,他可能不再关心第一组结果了。 中止并重新创建AJAX请求意味着用户可以获得更好的结果集。

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

您可以将此与bind / unbind结合使用,以便手动添加更改事件,然后在ajax请求启动时解除绑定,并在ajax请求完成时反弹。

正如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; }); } }); 

这里的实施稍微强一些。 基本上我们将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; } }; })($);