Cancelar llamadas AJAX previas

Hace pocos dias, mientras creaba el típico auto-suggest de los inputs de los formularios (en este caso de lugares – ciudades, calles, etc) vi que al tener que realizar una llamada AJAX al web service de geocoding de Google Maps APIs las llamadas se me solapaban dando lugar a un tiempo de espera mayor. Esto era debido a que la petición la lanzaba tras el evento onKeyUp, por lo que si se escribia muy rápido en el input, se lanzaban muchas peticiones muy seguidas y la experiencia de usuario era bastante mala. El efecto que se conseguia era que al acabar de escribir, las respuestas iban llegando y se iban cargando una detrás de otra e incluso parercía que el navegador llegaba a colapsarse.

Antes de cancelar las llamadas previas, unas se superponian a otras dando lugar a un tiempo de respuesta mayor y a una mala experiencia de usuario

La idea pues fue que al lanzar una nueva petición AJAX, se cancelara la anterior de manera que sólo hubiera solo una activa y por tanto sólo se cargaran datos durante las pausas de escritura en el input, y del mismo modo haciendo que mientras se escribía de forma rápida, no colapsar el servidor con llamadas haciendo todo el proceso de una forma menos trabada.

Cancelando las llamadas anteriores, se consigue que los resultados se muestren de forma más rápida y de forma menos trabada.

Entonces empecé a googlear como hacer esto, y encontré algunas respuestas pero ninguna me funcionó (como la de relanzar la petición para cancelar la anterior) y otras me parecieron muy complicadas para el cometido sencillo que tenia (aplicar un patrón observador). Incluso me encontré con quien decía que era imposible abortar la llamada AJAX desde el cliente (navegador).

Pues bie, gracias a jQuery encontré una solución muy sencilla aprovechando el evento beforeSend. Se trata de crear una variable global, donde guardaremos la conexión HTTPRequest, y en dicho evento beforeSend miraremos si hay alguna conexión, si la hay, abortaremos mediante la función abort() y meteremos la nueva conexión realizada en la variable global. Dando paso encontes al evento success, complete o error sólo con una conexión activa. Nuestra llamada AJAX con jQuery deberia quedar más o menos así, sin olvidar declarar la variable httpR como global:
[cc lang=”javascript”]
$.ajax({
url: ‘La URL a llamar’
beforeSend: function(data2){
/*httpR es la variable global donde guardamos la conexion*/
if(httpR){
/*Si habia alguna conexion anterior, la cancelamos*/
httpR.abort();
}
/*Guardamos la nueva conexion*/
httpR = data2;
},
success: function(data) {
/*Handler al recibir los datos OK*/
},
error: function(e, xhr){
/*Handler de error en la funcion*/
}
});
[/cc]
Para ver la mejora que se consigue, he preparado una demo que podéis ver aquí y descargar los archivos para probarlo.
Ver demoDescargar archivos