martes, 7 de junio de 2016

Ejecución de AJAX en forma síncrona

AJAX fue todo una revolución para el desarrollo web. Esta tecnología permite comunicarte con el servidor, enviar peticiones, y recibir la respuesta sin necesidad de refrescar la página.

El usuario lo ve como si fuera un programa interactivo, el pide algo, y el navegador envía la respuesta.

No es necesario volver a dibujar toda la página, sólo se actualizan los elementos necesarios.

AJAX fue creado para funcionar esencialmente en modo asíncrono. ¿Qué significa esto? Básicamente, que AJAX se ejecuta, y permite que el código que sigue después de la llamada AJAX continúe en ejecución. Además la página web sigue respondiendo a eventos y el usuario sigue interactuando de forma normal. Mientras, el objeto AJAX esta esperando la respuesta del servidor, sin interferir con la actividad de la página.Una vez terminada la petición AJAX al recibir una respuesta, se ejecuta el código que escribiste en la petición AJAX.

Esto es muy útil debido al tiempo de retardo. Después de todo al ejecutar AJAX envías un mensaje al servidor, el cual ejecuta como consecuencia de tu llamada un script de PHP. El script, puede consultar a la BD, crear XMLs, e incluso invocar a otros scripts en otros servidores, en fin puede hacer varios procedimientos. Es decir que no tienes idea de cuánto tiempo va a tomar de ejecución. Y una vez terminada la ejecución, te envía un string de respuesta, que a su vez recorre toda la red hasta el cliente.

Si AJAX no fuera asíncrono, todo ese tiempo de retardo la pantalla de tu navegador se congelaría, esperando la respuesta. Y tu página parecería mucho menos interactiva. Es cierto que no sería necesario refrescar por completo la página, y que solo estaría enviando y recibiendo strings,pero tomando en cuenta la red el tiempo de respuesta podría ser apreciable.

Ahora bien, no siempre necesitarás el modo asíncrono de AJAX. En ocasiones, cuando envías un a petición AJAX, necesitas esperar obligatoriamente la respuesta, y no puedes permitir la ejecución del código, ni la interacción con el usuario, hasta que tengas lista la respuesta.

Como ejemplo supongamos que tienes un enlace. Pero en el evento onClick, ejecutarás una petición AJAX para hacer una consulta a la BD y terminar de crear el enlace con los datos obtenidos. ¿Por que no cree el enlace como debía desde el inicio? Porque es una página interactiva, y mi usuario ha interactuado con ella, así que el transfondo ejecute peticiones AJAX y modifiqué la BD de datos. E incluso al dar el último click, el usuario pudo haber escogido una opción y eso afectará el contenido del enlace. E incluso tiene que ejecutar un proceso en la BD, antes de darme el enlace definitivo. Y el problema, es que si en el evento onClick, ejecuto mi petición AJAX, si esta funciona en modo asíncrono, continuará ejecutando el código de manera normal, es decir, lanzará mi enlace aún no terminado al final del evento.

Es solo una de las muchas situaciones en las que el modo asíncrono de AJAX no nos sirve. Por eso AJAX también cuenta con un modo síncrono. Como su nombre lo indica, este se ejecuta de manera síncrona es decir en secuencia, y el flujo de ejecución no puede continuar hasta que AJAX recibe una respuesta del servidor, por lo tanto es como si se ejecutará el código lineal. Incluso los eventos dejan de ser atendidos por Javascript.

¿Cómo podemos lograr esto? Veamos algunas formas.


1.-Forma 1


La primera forma será trabajando con el objeto AppXMLHttpReq().  El uso de este objeto es sencillo.
A continuación un código que muestra cómo ejecutarlo en forma síncrona:

     envioAjax  = AppXMLHttpReq();
    envioAjax.open("GET", "/php/llena_datos_envio.php?datos="+array, false);
     envioAjax.onreadystatechange=function()
        {
            if (envioAjax.readyState==4)
            {
             / /aqui va tu codigo        
           
                 return;
            }
        }    
     envioAjax.send(null);

Si ya sabes usar este objeto, notaste que no hubo mucho cambio. Simplemente al ejecutar el open, al final lleva el parámetro false, que es el que indica que el modo asíncrono sera cancelado y en su lugar se ejecutará en modo síncrono.Entonces la ejecución esperará al readyState=4 y entonces  ejecutará tu código. Una vez terminada la llamada AJAX, seguirá ejecutando el código que hayas escrito en el flujo normal.


2.-Forma 2

Una segunda forma es utilizando jquery. Mediante $.ajax. La cual también es sumamente sencilla:

$.ajax({
                      async: false,
                      type: 'GET',
                      url: "php/cps_generar_pedido.php?compra="+numero+"&destruye=SI",
                      success:function(resp){
                       / /aqui va tu codigo 
                      return (resp);                    
                     } } });

Una vez mas el truco es configurar el modo asíncrono en false. Solo cuando termine la petición AJAX se ejecutará el código en function, y una vez terminado el resto del código.


2.-Forma 3

Quizá ahora te preguntes si también puedes usar esto con $.post o $.post . Bueno en una sola línea , no es posible. Pero si se configura el objeto ajax, que al final usan $.post y $.get, se puede lograr en unas cuantas líneas. 

$.ajaxSetup({
          async: false
        });

$.post("/php/carrito_agregar.php",{key:llave,cantidad:$("#ArticuloC").text()}, function(resp){ 
if (resp !== "ERROR") {
alert("Producto agregado correctamente");
RegresarCarrito();
} else 
alert("Lo sentimos ocurrió un error"); });

$.ajaxSetup({
        async: true
      });

Como puedes ver es sencillo. Primero que nada con ajaxSetup, pones todas las llamadas a AJAX en false o modo síncrono.

Después ejecutas el $.post. En este caso le pase los argumentos key y cantidad. PHP me devolverá algo, y se ejecutará function. Solo cuando se haya ejecutado, podrá continuar la ejecución normal de mi programa.

Una vez hecho esto, pongo otra vez las llamadas en modo asíncrono que es el estándar, activando asynctrue

2.-Forma 4


Ahora bien el manejo de los tiempos en JavaScript es complicado. En ocasiones ni con todas estas técnicas se puede lograr el resultado deseado. En especial si anidas funciones dentro de otra. Hay una forma aún más segura de garantizar que el código se ejecute solamente cuando finalice una llamada AJAX.

Para esto usaremos $.when. Su uso es sencillo , pero mejor definamoslo con un ejemplo:

function carritoVacio(){ //regresa si el carrito esta vacío    
    return $.ajax({
        async: false,
        type: 'GET',
        url: "php/carrito_vacio.php",
        success:function(resp){    
          return resp;
        }
    })
}

$.when(carritoVacio().done(function(a1){            
       
                res = a1.search("NO");              
                if (res != -1)
                {                  
                  window.location = "/calcularEnvioPreeliminar/?compra="+compra;            
                }
                else
                {              
                    document.location.href=urlSitio+"/cuenta";
                 }
            }))

Primero que nada tengo mi función carritoVacio(), en mi caso es un AJAX, que me va a retornar si el carrito de compras tiene artículos o no. Ahora para asegurarme que este AJAX se ejecute por completo antes de continuar la ejecución del código, utilizó el $.when. Que lo único que indica, es que solamente cuando la función carritoVacio a terminado y regresado una respuesta, puedo ejecutar el código que se encuentra dentro del $.when.

Por lo tanto Javascript esperará pacientemente la ejecución del AJAX. Y luego ejecutara function, con el parámetro de entrada a1, que es lo que me retornó la función carritoVacio().

En mi caso de acuerdo a la respuesta invoco a un script u otro diferente, que es como controlo el flujo de navegación en la página.

En fin pueden utilizarse muchas técnicas, ya que si no estás acostumbrado a la ejecución asíncrona de ajax, puede ser todo un dolor de cabeza.

Ahora sabes como controlarlo, ¡a programar!




No hay comentarios.:

Publicar un comentario