martes, julio 03, 2007

AJAX PARA SUPERCAMPEONES o ¿Sabremos alguna vez qué es AJAX? (III)

Hala, de vuelta con el tema Ajax (la verdad es que da mucho juego el tema...). En esta tercera entrega de esta serie nos vamos a centrar en los siguientes dos temas:
  • Llamadas simultáneas: es decir, realizar múltiples llamadas a diferentes sitios a la vez.
  • Llamadas asíncronas secuenciales: este es un tema importante, saber cómo hacer llamadas asíncronas de forma ordenada.
Si no os habéis leído los posts anteriores, os recomiendo que lo hagáis:
Como sé que ya te los has leído, Nacho, puedes seguir con el siguiente punto ;P. En este post, terminamos la serie de AJAX PARA CAMPEONES o AJAX A PELO o AJAX KAMIKAZE, es decir, ajax para frikies.

Llamadas simultáneas
Una de los beneficios más importantes de trabajar con hebras de ejecución es que podemos crear tantas como nos permita el entorno (hardware, línea de comunicación, etc.) y el objeto XMLHttpRequest no es menos. Trabajando con AJAX podremos, por lo tanto, lanzar mútliples hilos de comunicación de forma simultánea que ejecutarán tareas distintas. Tendremos que tener cuidado de manejar correctamente las respuestas, de forma que sepamos siempre de quién es cada una.

En el ejemplo que os pongo aquí, podéis realizar tres llamadas simultáneas para que se carguen en los divs inferiores la página web que hayáis puesto. No es que esté demasiado currado pero menos es nada.

Ejemplo: http://www.nidea-soluciones.com/PruebasAjax/PruebaAjax5.html

Existen ciertas peculiaridades para que este ejemplo funcione:
  • Se ha creado una nueva función EnviarPeticionConParametro que además de realizar la petición le pasa un parámetro a la función que maneja la respuesta (aparte del objeto XMLHttpRequest).
  • Se ha implementado un Proxy al que llama la página para que se puedan hacer llamadas asíncronas CROSS-DOMAIN. Ésto lo explicaré otro día.
El código de la nueva función es el siguiente:










Como veis, introducimos un nuevo argumento llamado "parametro" que se le pasará a la función callback. Con este parámetro podremos decirle a la función callback qué objeto es el que ha realizado la llamada y ha respondido. Lo marco porque es muy importante ya que cada llamada tardará el tiempo que sea y devolverá el resultado en orden aleatorio. Tenemos que disponer de algún método que asocie la llamada con la respuesta.

Para entenderlo mejor, veamos el código de la página y cómo se realiza la llamada:



















En este caso, tenemos la función CargaURL(posicion), donde en posición se le pasa un 1, un 2 o un 3, dependiendo de qué botón es el pulsado. En base a ese número, se leerá el input correspondiente y se mostrará el panel de espera asociado. Finalmente se llama a la función EnviaPeticionConParametro y se le pasa la posición como parámetro final.

A la función que maneja la respuesta le llega el parámetro de la posición por lo que es capaz de poner la respuesta en el div correcto y oculta el div de espera correspondiente. De esta forma podemos tener una sola función que gestiona todas las llamadas y otra función que gestiona todas las respuestas. Si no lo hiciésemos así tendríamos que asociarle una función diferente a cada respuesta.

Os pongo un dibujo que como sabéis me molan y en el post anterior no tuve oportunidad de poner ninguno:











Las peticiones se envían al servidor, el cual las gestionará y tardará un tiempo x. Al ser asíncronas, las peticiones se evaluarán de forma simultánea y a medida que las vaya resolviendo irá mandando la respuesta. El orden de evaluación y respuesta no es fijo por lo que el orden de llegada de las peticiones no tiene por qué tener relación con el de salida. Es muy típico equivocarse con este concepto y escribir lo siguiente:

function MiFuncionQueRealizaMuchasCosas(){
// Primera accion asíncrona
ActualizaDatos();
MuestraDatosActualizados();
}

Error, al ser la función ActualizaDatos una llamada asíncrona a servidor, perderemos ese hilo de ejecución hasta que lo recoja el manejador de la respuesta. Por esto, la función MuestraDatosActualizados() no mostrará esos datos.

Llamadas asíncronas secuenciales
Por fin, el último ejemplo, lo último del AJAX PARA CAMPEONES. Este ejemplo se lo dedico con mucho cariño a Nacho porque sé que es tela de friki del Linux y en especial de Kubuntu y Ubuntu. Espero que te guste.

Como ya estaba harto de páginas html guarras con el texto a pelote decidí currarme un poquillo más este último ejemplo del post. En este ejemplo se realizan seis llamadas a servidor secuenciales, hasta que no se recibe la contestación de una no se realiza la siguiente. Podéis ver el ejemplo en la siguiente dirección (funciona mejor con Firefox porque el IE, a partir de la segunda vez, se pasa por el forro el delay que le tengo puesto en servidor):

http://www.nidea-soluciones.com/PruebasAjax/PruebaAjax6.html

Mola cantidad, eh? Por lo menos le damos un poco de aqué al tema. En fin, vamos al lío. ¿Cómo se hace esto? Aparte del tema gráfico (cada uno lo pone como más le gusta), la secuenciación de llamadas se realiza de la siguiente manera (os lo pongo en tres imágenes porque no me cabía en una):


















































Lo que hacemos es lo siguiente:
  1. Cuando el usuario pulsa sobre el botón, mostramos el divProgreso y le ponemos la primera imagen grande y su texto. Llamamos a la url Codigos/PruebaAjax6.aspx para ir a servidor.
  2. Cuando se recibe la respuesta, se pone la imagen en pequeño, se pone en grande la siguiente y la descripción de la acción y se realiza la llamada a la página con el parámetro del siguiente paso.
  3. Así sucesivamente hasta que en la última llamada, invocamos a la página redireccion.html. Obtenemos su código html y lo metemos dentro del div wrapper que engloba a toda la página.
Viéndolo en un dibujillo:















Es en las funciones callback donde realizamos la siguiente llamada.

El finaaaal deeeel veraaanooooo, llegoooo.....
Como todo, en algún momento hemos de llegar al final e igual que el verano todo acaba. Creo que con esta serie de ejemplos cubrimos la base de la comunicación asíncrona y del AJAX PARA CAMPEONES. Como os habréis percatado, el manejo del Javascript es fundamental (por Dios, nooooo), aunque, como veremos en posts posteriores, existen frameworks que nos ayudarán en nuestro cometido (un poco). Es importante que os deis cuenta que es indiferente el lenguaje de programación que utilicéis (yo lo he hecho todo en html plano), simplemente debe permitir hacer llamadas a funciones Javascript.

En próximos capítulos:
  • Frameworks Ajax
  • Llamadas Cross-Domain
Se me está ocurriendo hacer también algún post con el tema de los Mash-Ups.

8 comentarios:

Juan Menendez dijo...

Excelente post, realmente tienes un control del Ajax que alucino.
He aprendido con tu post mas que con los dos libros que Ajax que habia comprado. Enhorabuena

Manuel Cardenas Thorlund dijo...

Muchas gracias a ti por leer el post. Siempre es de agradecer que el trabajo de uno sirva para a otros. :)

Juan Menendez dijo...

Tengo problemas de compatibilidad con tu ejemplo en mi nueva web www.mastercafe.com/sql con IE7 funciona bien el Ajax en el link Envia a un amigo. Pero con FireFox, Opera, Safari,Flock no hay forma.
He revisado la definición que haces de objetoAjax y la he cambiado por la que yo uso y que funciona en esa web bastante bien (sobre todo para las votaciones y encuestas), también he variado la funcion CargaURL para agregar parametros de Url de llamada (asi no dependo de un formulario con un campo), el resto está igual y de hecho funciona muy bien en IE7. Tienes alguna idea de donde la he cagado?? Llevo ya 12 horas con esto y comienzo a sentirme muy torpe. Muchas gracias por anticipado.

Manuel Cardenas Thorlund dijo...

He estado mirando el código de tu página y parece ser que el problema se encuentra en que la llamada ajax se realiza correctamente y se devuelve la información al navegador pero no enlaza correctamente con la función de callback, por lo tanto siempre se queda con la imagen de espera, aunque ya haya recibido la información.

Al depurar el código aparece que al hacer la comparación objetoAjax.readystate==4 en la función EnviarPeticionConParametro, la propiedad readystate se encuentra 'undefined' por lo que no entra en dicha condición y no enlaza la petición con la función de respuesta. Prueba a quitarle esta condición a ver si te funciona.

Juan Menendez dijo...

En efecto al quitar la linea de readyState==4 funciona todos los navegadores (ya tengo curiosidad de saber como has conseguido depurar el código cuando a mi no me da errores en el navegador).
Por otro lado al quitar esta línea IE produce un error (mejor dicho 3 veces), por lo que voy a ver como consigo verificar el explorador en una linea anterior y ejecutar o no la sentencia.
Muchas gracias.
Por cierto que la web que has visitado funcionando (sin ajax) esta en www.forumgastronomico.com y se basa en construir cualquier web y cualquier parte a base de parámetros. Si quieres algo de información no dudes en decirmelo.
Saludos

Manuel Cardenas Thorlund dijo...

Para trabajar con javascript y depurar el codigo te recomiendo que te instales el complemento Firebug de Firefox. Puedes poner puntos de interrupción, depurar paso a paso, inspección de variables, rastrear las llamadas y respuestas a servidor, inspeccionar el DOM, etc. Vamos que es una herramienta muy útil para el tema AJAX.

Me agrada haberte sido de utilidad.

:Brunito! dijo...

GENIAL, impresionante la dedicacion que le das a tus post. Te felicito por la elaboración, la entrada es un poco vieja. Llegue por google, pero nuevamente tu post me fue de gran ayuda. Gracias nuevamente

Manuel Cardenas Thorlund dijo...

Gracias por tu comentario Brunito