Contenido

La mejor forma de usar las llamadas asincronas

12 dic

+ 3

Con este título la gente de IBM nos muestra un artículo bastante interesante en el que vemos una forma muy interesante de hacer nuestras llamadas asincronas mediante javascript (Ajax), principalmente se trata de una función que como veremos más adelante inteta cubrir todos los flancos que pueden hacer fallar la experiencia asincrona.

Función propuesta completa

function getResource(uri, data_callback, error_callback, timeout) {
    var tryAgain = function () {
      getResource(uri, data_callback, error_callback, timeout);
    }
    var r = new XMLHttpRequest();
    var timer = setTimeout(
        function() {
            r.abort();
            r.onreadystatechange = null;
            setTimeout(tryAgain, timeout);
        },
        timeout);
    r.open("GET", uri, true);
    r.onreadystatechange = function() {
        if (r.readyState != 4) {
            return;
        }
        clearTimeout(timer);  // readyState==4, borramos timer
        if (r.status==200) {  // "OK status"
              data_callback(r.responseText);
        }
        else if (r.status==304) {
            // "Not Modified": No modificamos la salida
        }
        else if (r.status >= 400 && r.status < 500) {
            // Posible error, posible URI erronea
            error_callback(r)
        }
        else if (r.status >= 500 && r.status < 600) {
            // Server error, volvemos a lanzar con un poco de demora
            setTimeout(tryAgain, timeout);
        }
        else {
            error_callback(r);
        }
    }
    r.send(null);
    return r;
}

Función detallada

Empezando de arriba a abajo, tenemos la variable tryAgain, que no es más que la definición de una función que hace la misma llamada que hemos hecho inicialmente. Esta variable será usada para lanzar la función en caso de necesitar relanzarla por algún motivo.

var tryAgain = function () {
     getResource(uri, data_callback, error_callback, timeout);
   }

Sobre la variable r, recae la responsabilidad de albergar el objeto XMLHttpRequest() que hará posible el asincronismo. Aunque yo propongo algo más completo para asegurarnos que IE6 no se quede fuera de juego.

var r = new XMLHttpRequest();
//Más completo
var r = (XMLHttpRequest)?new XMLHttpRequest():new ActiveXObject('Microsoft.XMLHTTP');

Ya con el objeto principal cargado, declaramos la variable timer, que al igual que tryAgain solo será llamada en el caso en se requiera. Esta función se encargará abortar la transacción asíncrona al cubrir el tiempo timeout dado.

var timer = setTimeout(
        function() {
            r.abort();
            r.onreadystatechange = null;
            setTimeout(tryAgain, timeout);
        },
        timeout);

Una vez preparado el camino con las variables necesarias para el funcionamineto, solo nos queda hacer la llamada, en este caso por GET, y controlar los valores retornados para accionar una funcionalidad u otra.

Tratando la respuesta

Al igual que en el ejemplo anterior, la respuesta tambien debería ser tratada teniendo en cuenta un timeout que nos evitará demoras innecesarias. Para ello definiremos nuestra función usando una estructura similar a esta.

var other_data = null;
function processData(this_data) {
    var delay = 1000;     // Esperamos 1 segundo
    if (other_data == null) {
        setTimeout(function() { processData(this_data); }, delay);
        return;
    }
    // Tenemos this_data y other_data
    displayThisAndThat(this_data, other_data);
    // Reseteamos other_data, ya la hemos usado
    other_data = null;
}
// Ejemplo de uso
getResource(uri2,processData,errorData, 5000);

Comentar

#

Me reservo el derecho de eliminar y/o modificar los comentarios que contengan lenguaje inapropiado, spam u otras conductas no apropiadas en una comunidad civilizada. Si tu comentario no aparece, puede ser que akismet lo haya capturado, cada día lo reviso y lo coloco en su lugar. Siento las molestias.