2010-01-05 10 views
7

Mam pole tekstowe, które za każdym razem, gdy użytkownik wprowadza literę, wykonuję wyszukiwanie z prośbą o ajax i pokazuję wynik "na żywo" dla użytkownika. Często, gdy użytkownik wpisuje litery, zajmuje więcej czasu, niż żądanie użytkownika, aby wprowadzić nową literę, a zatem nowe żądanie jest składane przed pierwszym zakończeniem. Byłoby znacznie lepiej, gdyby pierwszy mógł się skończyć, zanim zrobię następną prośbę. Czy istnieje dobry sposób na złożenie nowego wniosku tylko po zakończeniu ostatniego wniosku?Żądanie ajax Jquery, czekaj na najnowszą prośbę, aby zakończyć

To jest mój kod 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 
      } 
     }); 
    } 
}); 

Odpowiedz

9

Można utworzyć wartość logiczną, która będzie zawierała wartość true lub false w zależności od tego, czy żądanie już wystąpiło. Ustaw ją na true, gdy uruchomisz żądanie i ustawisz z powrotem na false w funkcji zwrotnej.

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

Dzięki! Właśnie tego szukałem. Ale z jakiegoś powodu podczas wpisywania tekstu wydaje mi się, że za każdym razem, gdy wpisuję literę, jest trochę powikłana, a każda litera pojawia się z pewnym opóźnieniem. Żądanie ajax należy przesłać asynchronicznie, więc nie powinno to wpłynąć na pole tekstowe, gdyby było? – Martin

+1

Lepiej byłoby przypisać funkcję z kodem czyszczenia, np. 'Request_in_progress' w ustawieniu' complete', zamiast 'success' w przypadku niepowodzenia żądania. –

0

Można wykorzystać ajaxComplete aby wiedzieć, gdy żądanie zostało zakończone przed podjęciem nowego żądania.

Możesz połączyć to z bind/unbind, aby zdarzenie change zostało dodane ręcznie, a następnie niezwiązane, gdy zaczyna się żądanie ajax, i odskakuje po zakończeniu żądania ajax.

8

Możesz przerwać żądanie AJAX. Śledź żądanie jako zmienną i przerwij je przed ponownym zainicjowaniem żądania.

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

Ma to dodatkową zaletę, że lepiej reaguje na dane wprowadzane przez użytkownika. Jeśli użytkownik wpisał coś więcej, odkąd zainicjowano pierwsze żądanie, prawdopodobnie nie dba już o pierwszy zestaw wyników. Przerwanie i odtworzenie żądania AJAX oznacza, że ​​użytkownik otrzymuje lepszy zestaw wyników.

0

Jak już wspomniano ceejayoz, należy przerwać poprzednie żądanie. (Oczekiwanie na wniosek pozwoli użytkownikom mad jeśli nie mogą wpisać jak chcą i prefering starsze żądania ponad nowszych sprawia wyniki nieaktualne.). Więc co:

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

Tutaj jest nieco bardziej wytrzymałe realizacja. Zasadniczo zapisujemy obiekt ajax (tzn. Obiekt obietnicy) w celu zamknięcia, aby kolejne wywołania mogły na niego wyglądać. Jeśli następne wywołania wykryją, że status żądania jest oczekujący, spowoduje to dodanie wywołań zwrotnych do oczekującego żądania zamiast generowania nowego żądania. jQuery uruchomi wszystkie wywołania zwrotne w tej samej kolejności, w jakiej zostały dodane. Istnieje jednak możliwość, że ten sam wywołujący próbuje ponownie utworzyć żądanie. Aby chronić się przed tym, dodałem parametr callerId. Jeśli ten sam wywołujący ponownie wysłał żądanie, podczas gdy poprzednie żądanie było nadal w toku, po prostu zignorujemy to żądanie. Dla kompletności dodałem również cachedValues. Więc jeśli zapytanie ajax zostało już wykonane, nie zrobimy tego ponownie.

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