2011-11-05 33 views
31

Duplicar posible:
Kill Ajax requests using JavaScript using jQueryCancelar las solicitudes AJAX en vuelo utilizando Jquery .ajax?

Aquí está el código simple que estoy trabajando con:

$("#friend_search").keyup(function() { 

    if($(this).val().length > 0) { 
     obtainFriendlist($(this).val()); 
    } else { 
     obtainFriendlist(""); 
    } 

}); 

function obtainFriendlist(strseg) { 

    $.ajax({ 
     type: "GET", 
     url: "getFriendlist.php", 
     data: "search="+strseg, 
     success: function(msg){ 
     UIDisplayFriends(msg); 
     } 
    }); 
} 

Esencialmente, si un evento keyup se dispara antes de que vuelva la función obtainFriendlist un resultado (y desencadena UIDisplayFriends (msg), necesito cancelar la solicitud en vuelo. El problema que he estado teniendo es que ellos ld up, y de repente la función UIDisplayFriends se dispara repetidamente.

Muchas gracias, y el asesoramiento es útil también

Respuesta

19

El valor de retorno de $.ajax es un objeto XHR que puede llamar en acciones. Para abortar la función que haría algo como:

var xhr = $.ajax(...) 
... 
xhr.abort() 

Puede ser inteligente para añadir un poco de supresión de rebotes así a aliviar la carga en el servidor. Lo siguiente solo enviará una llamada XHR solo después de que el usuario haya dejado de escribir durante 100 ms.

var delay = 100, 
    handle = null; 

$("#friend_search").keyup(function() { 
    var that = this; 
    clearTimeout(handle); 
    handle = setTimeout(function() { 
     if($(that).val().length > 0) { 
      obtainFriendlist($(that).val()); 
     } else { 
      obtainFriendlist(""); 
     } 
    }, delay); 
}); 

Una tercera cosa que realmente debe hacer es filtrar las respuestas XHR en función de si o no la solicitud sigue siendo válida:

var lastXHR, lastStrseg; 

function obtainFriendlist(strseg) { 
    // Kill the last XHR request if it still exists. 
    lastXHR && lastXHR.abort && lastXHR.abort(); 

    lastStrseg = strseg; 
    lastXHR = $.ajax({ 
     type: "GET", 
     url: "getFriendlist.php", 
     data: "search="+strseg, 
     success: function(msg){ 

     // Only display friends if the search is the last search. 
     if(lastStrseg == strseg) 
      UIDisplayFriends(msg); 
     } 
    }); 
} 
+1

Me gusta lo que haces con el retraso, eso es bueno. Sin embargo, ¿no existe aún el riesgo de que las solicitudes se acumulen si el usuario es un escritor lento, lo que activa una nueva solicitud de Ajax con cada pulsación de tecla? –

+1

Todavía sería un riesgo, por lo que querría aplicar ambas estrategias, cancelar la consulta anterior y el método anterior para reducir las llamadas al servidor. Una tercera pantalla estaría validando que la salida aún coincida con la solicitud. –

+1

Excelente. gracias, esto es muy informativo – TaylorMac

0

¿Cómo sobre el uso de una variable, por ejemplo isLoading, que se establece a través de cierto uso de la opción beforeSend (jqXHR, ajustes) para .ajax, y luego usar el completa la configuración para volver a establecer la variable en falso. ¿Entonces solo valida con esa variable antes de activar otra llamada ajax?

var isLoading = false; 
$("#friend_search").keyup(function() { 

    if (!isLoading) { 
     if($(this).val().length > 0) { 
      obtainFriendlist($(this).val()); 
     } else { 
      obtainFriendlist(""); 
     } 
    } 

}); 

function obtainFriendlist(strseg) { 

    $.ajax({ 
     type: "GET", 
     url: "getFriendlist.php", 
     beforeSend: function() { isLoading = true; }, 
     data: "search="+strseg, 
     success: function(msg){ 
     UIDisplayFriends(msg); 
     }, 
     complete: function() { isLoading = false; } 
    }); 
} 
+1

¿No sería lo contrario? Si el usuario escribe "PRUEBA" antes de que el XHR regrese, las pulsaciones de tecla para E, S y T se ignorarían y la respuesta del servidor sería solo para "T". –

Cuestiones relacionadas