2010-01-05 138 views
7

我有一个文本框,每次用户输入一个字母,我用ajax请求进行搜索,并显示结果“live”给用户。通常,当用户键入字母时,要求制作的时间比用户输入新字母需要更长的时间,因此在第一个字母结束之前发出新的请求。如果在我做下一个请求之前第一个可以结束会更好。如果最新的请求已经结束,是否有一种很好的方式来提出新的请求?Jquery 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 
      } 
     }); 
    } 
}); 

回答

9

根据是否有请求已经发生,您可以创建一个布尔值来保持true或false。在您的回调函数中启动请求并将其设置回false时,将其设置为true。

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 
      } 
     }); 
    } 
}); 
+0

谢谢!这正是我正在寻找的。但出于某种原因,当我输入文字时,似乎每次我输入一封信都是一个小错误,每个字母都会显示一种延迟。 ajax请求应该发送异步,所以它不应该影响文本框应该吗? – Martin 2010-01-05 22:57:08

+1

如果请求失败,最好在'complete'设置中使用像'request_in_progress'这样的清理代码,而不是'success'。 – 2012-10-30 16:43:46

0

您可以利用ajaxComplete让你知道当一个请求作出新的请求之前完成。

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

8

您可以放弃AJAX请求。跟踪请求作为变量,并在重新启动请求之前中止它。

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

这具有更多的优点,可以更好地响应用户输入。如果用户在第一次请求发起后输入了更多内容,他可能不再关心第一组结果。中止并重新创建AJAX请求意味着用户可以获得更好的结果集。

0

正如ceejayoz已经提到的那样,您应该放弃先前的请求。 (等待请求将使用户,如果他们不能键入疯狂,因为他们想与prefering在较新的旧的请求,得到的结果也过时了。)那么,关于:

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; 
     } 
    }; 
})($);