2010-01-05 21 views
7

Tengo un cuadro de texto que cada vez que un usuario ingresa una letra realizo una búsqueda con una solicitud de ajax y muestro el resultado "en vivo" para el usuario. A menudo, cuando un usuario escribe las letras tarda más tiempo para que se realice la solicitud que para que el usuario ingrese una nueva letra, por lo tanto, se realiza una nueva solicitud antes de que la primera haya finalizado. Sería mucho mejor si el primero pudiera terminar antes de hacer la siguiente solicitud. ¿Hay una buena manera de hacer una nueva solicitud solo si la última solicitud ha finalizado?Solicitud de jquery ajax, esperar la última solicitud para terminar

Este es mi código de 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 
      } 
     }); 
    } 
}); 

Respuesta

9

Puede crear un valor booleano que sea verdadero o falso dependiendo de si ya hay una solicitud en curso. Establézcalo en verdadero cuando comience una solicitud y vuelva a establecerlo en falso en su función de devolución de llamada.

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

Gracias! Esto era exactamente lo que estaba buscando. Pero por alguna razón al escribir en mi texto, parece que cada vez que ingreso una carta es un poco problemático y cada letra aparece con una especie de retraso. La solicitud de AJAX debe enviarse de manera asíncrona, por lo que no debería afectar al cuadro de texto, ¿o sí? – Martin

+1

Sería mejor asignar una función con código de limpieza como 'request_in_progress' en la configuración' completa' en lugar de 'success' en caso de que la solicitud falle. –

0

Puede utilizar ajaxComplete para que sepa cuando una solicitud ha terminado antes de hacer una nueva solicitud.

Puede combinar esto con vincular/desvincular para que el evento de cambio se agregue una vez manualmente, luego se desactive cuando se inicie una solicitud de ajax, y rebote cuando finalice la solicitud de ajax.

8

Puede cancelar una solicitud AJAX. Realice un seguimiento de la solicitud como una variable, y abortar antes de volver a iniciar la solicitud.

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

Esto tiene la ventaja adicional de ser más receptivo a la entrada del usuario. Si el usuario ha escrito algo más desde que se inició la primera solicitud, probablemente ya no le preocupe el primer conjunto de resultados. Anular y volver a crear la solicitud de AJAX significa que el usuario obtiene un mejor conjunto de resultados.

0

Como ya mencionó ceejayoz, debe cancelar la solicitud anterior. (A la espera de la solicitud hará que los usuarios loca si no pueden escribir lo que quieran y prefiriendo las peticiones de más edad más de los más nuevos hace que los resultados no actualizados..) Entonces, ¿qué acerca de:

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

Aquí está un poco más robusta implementación. Básicamente guardamos el objeto ajax (es decir, el objeto promesa) en el cierre para que las siguientes llamadas puedan verlo. Si las próximas llamadas descubren que el estado de la solicitud está pendiente, agregará devoluciones de llamada a esa solicitud pendiente en lugar de generar una nueva solicitud. jQuery activará todas las devoluciones de llamadas en la misma secuencia en que fueron agregadas. Sin embargo, existe la posibilidad de que la misma persona que llama intente crear una solicitud una y otra vez. Para protegerme de eso, agregué el parámetro callerId. Si la misma persona que llama hizo una solicitud nuevamente mientras la solicitud anterior aún estaba pendiente, simplemente ignoramos esa solicitud. Para completar, también agregué cachedValues. Entonces, si ya se realizó la solicitud de ajax, no lo hacemos nuevamente.

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