2010-01-05 25 views
7

Ho una casella di testo che per ogni volta che un utente immette una lettera eseguo una ricerca con una richiesta Ajax e mostra il risultato "live" per l'utente. Spesso quando un utente digita le lettere richiede più tempo per la richiesta che per l'utente di inserire una nuova lettera, quindi viene fatta una nuova richiesta prima che il primo sia terminato. Sarebbe molto meglio se il primo potesse finire prima di fare la prossima richiesta. C'è un buon modo per fare solo una nuova richiesta se l'ultima richiesta è finita?Richiesta Jjery ajax, attendere l'ultima richiesta di completamento

Questo è il mio codice 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 
      } 
     }); 
    } 
}); 

risposta

9

È possibile creare un valore booleano che verrà mantenuto vero o falso a seconda se è già in corso una richiesta. Impostare su true quando si avvia una richiesta e reimpostarla su false nella funzione di callback.

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

Grazie! Questo era esattamente quello che stavo cercando. Ma per qualche ragione quando digito il mio testo sembra che ogni volta che inserisco una lettera è un po 'buggato e ogni lettera si presenta con una sorta di ritardo. La richiesta Ajax dovrebbe essere inviata asincrona, quindi non dovrebbe influenzare la casella di testo dovrebbe? – Martin

+1

Sarebbe meglio assegnare una funzione con codice cleanup come 'request_in_progress' nell'impostazione' complete' piuttosto che 'success' nel caso in cui la richiesta fallisca. –

0

È possibile utilizzare ajaxComplete in modo da sapere quando una richiesta è terminata prima di effettuare una nuova richiesta.

È possibile combinare ciò con bind/unbind in modo che l'evento change venga aggiunto una volta manualmente, quindi non associato quando viene avviata una richiesta ajax e rebound quando termina la richiesta ajax.

8

È possibile interrompere una richiesta AJAX. Tieni traccia della richiesta come variabile e interrompila prima di riavviare la richiesta.

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

Questo ha il vantaggio di essere più reattivo all'input dell'utente. Se l'utente ha digitato qualcosa di più da quando è stata avviata la prima richiesta, probabilmente non si preoccupa più della prima serie di risultati. Annullare e ricreare la richiesta AJAX significa che l'utente ottiene un migliore insieme di risultati.

0

Come già detto ceejayoz, è necessario interrompere la richiesta precedente. (Attesa per la richiesta renderà gli utenti pazza se non possono digitare come vogliono e prediligendo le vecchie richieste su quelli più recenti rende i risultati obsoleti..) E per quanto riguarda:

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

Qui sta un po 'più robusto implementazione. In pratica, salviamo l'oggetto ajax (cioè l'oggetto promessa) nella chiusura in modo che le chiamate successive possano guardarlo. Se le chiamate successive rilevano che lo stato della richiesta è in sospeso, aggiungerà i callback a quella richiesta in sospeso anziché generare una nuova richiesta. jQuery attiverà tutte le callback nella stessa sequenza in cui sono state aggiunte. Tuttavia esiste la possibilità che lo stesso chiamante stia tentando di creare la richiesta ancora e ancora. Per proteggerlo ho aggiunto il parametro callerId. Se lo stesso chiamante ha effettuato nuovamente la richiesta mentre la precedente richiesta era ancora in sospeso, ignoriamo la richiesta. Per completezza ho anche aggiunto cacheValues. Quindi, se la richiesta Ajax fosse già stata fatta, non ce la faremo più.

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