martes, 23 de abril de 2013

Aprende Ajax desde cero

Aprende Ajax desde cero

 AJAX es el acrónimo de Asynchronous JavaScript And XML o lo que es lo mismo Javascript asíncrono y xml. Se trata de una tecnología para hacer peticiones asíncronamente y por lo tanto no tener que refrescar toda la página para interactuar con el servidor. Estas llamadas se hacen utilizando Javascript a través del objeto XmlHttpRequest, que sirve de interfaz entre los datos de la página y el servidor.


 Las posibilidades son infinitas, por ejemplo la recarga de datos en combos dependientes, inputs con autocompletado para búsquedas, controles de pestañas más fluidos, formularios de login, etc. Al final el objetivo que buscamos con Ajax es obtener aplicaciones web RIA (Rich Internet Applications) o lo que es lo mismo, aplicaciones dinámicas y fluidas, independientes del sistema operativo y que sean agradables para el usuario.

Objeto XmlHttpRequest

 A continuación hablaré de cada uno de los métodos y propiedades de que dispone el objeto XmlHttpRequest.
·         Disponemos de las siguientes propiedades:
o   readyState: Se trata de un valor numérico que indica el estado de la petición. Se utiliza sobre todo en el evento onreadystatechange de llamadas asíncronas (visto más adelante). Posibles valores:

§  0: No inicializado. El objeto ya se ha creado pero todavía no se ha realizado la petición mediante el método send.
§  1: Abierto. Se acaba de llamar al método send.
§  2: Enviando. Se está enviando la petición al servidor.
§  3: Recibiendo. Se está recibiendo la respuesta del servidor.
§  4: Completado. Ya se ha obtenido la respuesta del servidor y podemos acceder a la propiedad responseText y responseXml.

o   responseText: Almacena la respuesta a la petición en forma de texto.
o   responseXML: Almacena la respuesta a la petición en forma de xml. Por ejemplo si la url a la que llamamos devuelve código html, podremos insertarlo directamente en el DOM haciendo un appendChild mediante javascript. En el caso de responseText se puede insertar a través de la propiedad innerHTML.
o   status: Código http devuelto por el servidor. Por ejemplo, para comprobar que una petición ha obtenido una respuesta válida se comprueba que el código sea 200.
o   statusText: Es el texto equivalente al status code devuelto por el servidor.

·         Estos son los métodos disponibles:
o   abort(): Aborta la petición.
o   getAllResponseHeaders(): Devuelve todas las cabeceras de la respuesta.
o   getResponseHeader(‘cabecera’):  Devuelve el contenido de la cabecera especificada.
o   onreadystatechange: Es un evento que se lanza cada vez que cambia el estado de la petición. Para comprobar el estado tenemos la propiedad readyState.
o   open(’metodo’, ‘url’, async): Establece el tipo de petición y la url. Opcionalmente se puede indicar si la petición será síncrona o asíncrona y el usuario y password si se requiere autenticación.
o   send(contenido): Es el método que lanza la petición. Si usamos el método POST, habrá que pasarle los datos por parámetro. En el caso de GET, bastará con enviar null.
o   setRequestHeader(‘cabecera’, ‘valor’) : Sirve para establecer una cabecera personalizada. Se suele utilizar para establecer el tipo de contenido como codificado en las peticiones por POST .

Ejemplo paso a paso

 Se trata de un ejemplo muy sencillo en ASP.NET que nos permitirá tener una visión global del funcionamiento de las peticiones AJAX. Consistirá en obtener la hora del servidor sin refrescar la página. En primer lugar hablaré de la parte del cliente y a continuación de la parte del servidor.
 En la parte del cliente crearemos un archivo Ajax.js en el que añadiremos toda la lógica necesaria. Lo primero que necesitamos para trabajar con Ajax es un objeto XmlHttpRequest , pero como todos sabemos, no todos los navegadores utilizan la misma notación, por lo que crearemos una función que nos devolverá una instancia de este objeto dependiendo del navegador:
//Obtiene una instancia del objeto XmlHttpRequestfunction ObtenerObjetoAjax() {

var peticionHttp = null;
try {
//Comprobación para navegadores Firefox, Opera y Safari
if (window.XMLHttpRequest) {
peticionHttp = new XMLHttpRequest();
}
//Comprobación para navegadores IE
else if (window.ActiveXObject) {
//Comprobamos para JavaScript 5.0. Si da error,
//creamos un objeto con la versión anterior
try {
peticionHttp = new ActiveXObject("Microsoft.XMLHTTP2");
}
catch (e1) {
peticionHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
}
//Comprobación para IceBrowser
else if (window.createRequest) {
peticionHttp = window.createRequest();
}
//Si el navegador no soporta ajax retornamos null
else {
peticionHttp = null;
}
}
catch (e2) {
return null;
}
return peticionHttp;
}

 A continuación crearemos la función que envíe la petición al servidor:
//Realiza una petición asíncronamente al servidor

//url: Url dónde realizar la petición

//tipoResultado: Puede set 'XML' o 'TEXT'

//metodo: Tipo de petición. Puede ser 'GET' o 'POST'

//parametrosPost: Parámetros para peticiones tipo POST

//cacheDatos: Indica si se cachearán las peticiones por GET en IE

//funcionPintarDatos: Función para manejar las acciones a realizar en 

//                    cada estado de la peticiónfunction ObtenerDatosASinc(url, tipoResultado, metodo, parametrosPost, 

     cacheDatos, funcionPintarDatos) {

try {
//Obtenemos la instancia del objeto XmlHttpObject
var objAjax = ObtenerObjetoAjax();
//Nos suscribimos al evento onreadystatechange para manejar los
//posibles estados de la petición para que se lance la
//función recibida por parámetro
objAjax.onreadystatechange = function() {
switch (objAjax.readyState) {
//Petición no inicializada
case 0:
break;
//Conexión con el servidor establecida
//(llamada a send)
case 1:
break;
//Enviando petición
case 2:
//Aquí se podría mostrar un gif que indicase
//que se está realizando la petición al servidor
//Habría que ocultarlo en el caso 4,
//cuando ya se ha recibido la respuesta
break;
//Recibiendo petición
case 3:
break;
//Respuesta del servidor recibida
case 4:
//Si el status code de la respuesta es 200,
//todo ha ido bien
if (objAjax.status == 200) {
switch (tipoResultado) {
case 'XML':
funcionPintarDatos(objAjax.responseXML);
break;
case 'TEXT':
funcionPintarDatos(objAjax.responseText);
break;
default:
funcionPintarDatos(objAjax.responseText);
break;
}
}
//Si no, no ha ido bien y retornamos el texto
//equivalente al status code
else {
switch (tipoResultado) {
case 'XML':
funcionPintarDatos(
'<a>' + objAjax.statusText + '</a>');
break;
case 'TEXT':
funcionPintarDatos(objAjax.statusText);
break;
default:
funcionPintarDatos(objAjax.statusText);
break;
}
}
break;
//No hay más estados en la petición,
//por lo que no hacemos nada
default:
break;
}
};
//Si realizamos la petición por POST
if (metodo == 'POST') {
//Si no recibimos parámetros ponemos la variable a null
if (parametrosPost == 'undefined' || !parametrosPost) {
parametrosPost = null;
}
objAjax.open('POST', url, true);
objAjax.setRequestHeader('Content-type',
'application/x-www-form-urlencoded');
objAjax.send(parametrosPost);
}
//Si no la realizamos por GET.
else {
//Internet Explorer cachea las peticiones por GET,
//por lo que agregamos un parametro random si se
//quiere evitar
if (!cacheDatos) {
var separadorUrl =
(url.indexOf('?') > -1) ? '&' : '?';
url += separadorUrl + 'rndCache=' + Math.random();
}
objAjax.open('GET', url, true);
objAjax.send(null);
}
}
catch (e) {
//Si hay un error mostramos su mensaje
alert(e.message);
}
}



 Para hacer la prueba tenemos que crear dos funciones más, la que pinte los datos y a la que llamaremos desde la página. La petición será por GET y la respuesta se devolverá en forma de texto.
 El parámetro que se pasa como false a la función ObtenerDatosASinc indica que no se cacheará la respuesta, cosa que en Internet Explorer ocurre por defecto para las peticiones por GET. De este modo siempre nos devolverá el nuevo valor de la respuesta del servidor.
//Realiza una petición asíncrona al servidor para obtener la hora
function ObtenerHora() {
   
ObtenerDatosASinc('HoraServidor.aspx', 'TEXT', 'GET', null, false, PintarHora);
}   
//Función para pintar los datos recibidos del servidor
function PintarHora(datos) {
   
 document.getElementById('idDivDestino').innerHTML = datos;   
}

  A continuación crearemos una página de prueba en la que agregaremos un div en el que se pintarán las respuestas del servidor, y un botón que será el que lance la petición. Como se observa en el código, añadiremos una referencia al archivo Ajax.js, que es dónde hemos metido toda la lógica de cliente.
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="PaginaPrueba.aspx.cs"
Inherits="PaginaPrueba" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title></title>
     <script language="javascript" type="text/javascript" src="Ajax.js"></script>
 </head>
<body>
    <form id="form1" runat="server">
    <asp:Button runat="server" ID="btnHora" Text="Obtener hora del servidor"
OnClientClick="ObtenerHora(); return false;" />
    <div id="idDivDestino">
    </div>
    </form>
</body>
</html>

  Por último crearemos una nueva página llamada HoraServidor.aspx, que retornará la hora del servidor en la respuesta:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="HoraServidor.aspx.cs"
Inherits="HoraServidor" %>
<% 
    Response.Clear();
    Response.Write(DateTime.Now.ToString());
%>

Conclusión


 En este artículo se han descrito los conceptos básicos de la tecnología Ajax y sus ventajas, además de un ejemplo para facilitar su comprensión. Aparentemente puede parecer tedioso, pero una vez te acostumbras a usarlo, el concepto de página web cambia para siempre, ya que nos permite crear aplicaciones más fluidas y similares a las de escritorio de toda la vida.
 Esto es la base de Ajax, y por supuesto, existen numerosos frameworks con herramientas que facilitan el desarrollo en tiempo y diseño. Por ejemplo ASP.NET posee la librería Atlas que nos permite hacer uso de esta tecnología casi sin pensar en cómo funciona, ya que se encarga de gestionar todas las operaciones internamente.
 Otra librería muy recomendada es AjaxPro, ya que es potente y a la vez ligera. Con ella podemos realizar llamadas a funciones de clases del servidor de manera muy sencilla. En su página web tienen un ejemplo como el que os he mostrado, usando esta librería, que como comprobaréis reduce bastante la complejidad.
 Espero que después de leer este tutorial le cojáis gusto a esta tecnología, porque la tendencia actual en el diseño de aplicaciones es la distribución de servicios, y nada mejor que una aplicación web con una buena interfaz RIA para centralizarlos y explotarlos desde cualquier lugar.

No hay comentarios:

Publicar un comentario