AJAX o Asynchronous JavaScript And XML, es una técnica que permite realizar peticiones a un servidor web haciendo uso de Javascript, esperando una respuesta del servidor en XML.
En términos generales esto es correcto, sin embargo, en la práctica veremos que hay muchas formas de responder a peticiones AJAX no solo con XML sino con JSON, texto fijo, HTML, nuestro propio protocolo, etc. Es más, nuestra petición puede ser en otro lenguaje que no sea Javascript (siempre y cuando sea un lenguaje del lado cliente).
Dicho esto, tiene que quedar claro que AJAX no necesariamente está amarrado a Javascript y XML pero lo está en la gran mayoría de casos. Además cada vez es más común ver la combinación Javascript y JSON (Javascript Object Notation) por su facilidad de uso y eficiencia.
Funcionamiento básico de AJAX
En Javascript, la implementación básica de AJAX se realiza utilizando un objeto llamado XMLHttpRequest que viene con el lenguaje (en realidad viene con el navegador más que con el lenguaje). Este objeto es el que se utiliza para realizar las peticiones AJAX al servidor.
Antes de realizar la implementación básica es necesario que entiendas el flujo de como funciona AJAX:
- En el lado cliente se crea un objeto de tipo
XMLHttpRequestpara realizar la petición al servidor. (Las peticiones solo se pueden hacer dentro del mismo dominio por razones de seguridad). - En el lado cliente se arma la petición y esta se envía al servidor web.
- El servidor interpreta la petición y devuelve
algo(HTML, XML, JSON, Texto, Imagen, Video, etc). Estealgo, puede ser cualquier cosa que decida devolver tu servidor. La petición que se realiza con AJAX es muy parecida a la que se realiza a través del navegador. - El cliente recibe este algo y lo procesa como mejor le parezca. Puede ser: mostrarlo como mensaje, cambiar algún elemento de la pantalla, etc.
Implementación básica de AJAX
La primera implementación de AJAX que voy a realizar será utilizando de forma directa el objeto XMLHttpRequest y solicitando tres páginas web con diferentes contenidos.
El lado servidor
Antes de comenzar con AJAX, voy a preparar mi servidor para que esté listo para responder a las peticiones AJAX que voy a realizar. Para ello, voy a crear tres páginas web pequeñas dentro de la raíz de mi servidor web y las voy a llamar: pagA.html, pagB.html, pagC.html.
El contenido de las páginas será el siguiente:
pagA.html
pagB.html
pagC.html
<table border="1"><tr> <th>ID</th><th>MARCA</th><th>PRECIO</th> </tr><tr><td>456</td><td>Invalida</td><td>10.55</td> </tr><tr><td>378</td><td>Percha</td><td>11.33</td> </tr><tr><td>326</td><td>Marcon</td><td>7.55</td> </tr></table>
ID,MARCA,PRECIO,456,Invalida,10.55,378,Percha,11.33,326,Marcon,7.55
[["ID","MARCA","PRECIO"],["456","Invalida","10.55"],["378","Percha","11.33"],["326","Marcon","7.55"]]
Si te fijas con atención, las tres páginas devuelven el mismo contenido. La primera devuelve una tabla en HTML con todo el contenido listo para ser mostrado (muy parecido a XML). La segunda página devuelve todos los valores separados por comas y la tercera página devuelve los valores en un formato llamado JSON.
Si colocas estas tres páginas en tu servidor web (raíz) puede entrar a http://localhost/pagA.html, http://localhost/pagB.html y http://localhost/pagC.html y deberías ver el siguiente contenido:
http://localhost/pagA.html
http://localhost/pagB.html
http://localhost/pagC.html
Listo!! Con esto nuestro servidor web está listo. Ahora lo que falta es hacer la parte del lado cliente dónde vamos a realizar las peticiones correspondientes.
El lado cliente
Lo primero que tenemos que hacer es una página web que sea la que realice las peticiones AJAX. Te doy la estructura de la página la cual llamaremos ajax.html.
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Primera prueba con AJAX</title> </head> <body> <div style="border:1px solid #ddd; background-color:#eee; text-align:center;"> <input type="button" value="Dame A" /> <input type="button" value="Dame B" /> <input type="button" value="Dame C" /> </div> <div id="contenido" style="text-align:center;"> Aun no hay contenido. Presione algun boton. </div> </body> </html>
Esta página lo único que hace es mostrar tres botones y una sección diciendo que aún no hay contenido. La idea es que al presionar los botones aparezca el contenido en la página, dentro del div con id = contenido.
Ahora necesitamos crear el código Javascript para las peticiones AJAX:
Lo primero que haré será crear una función que me devuelva el objeto XMLHttpRequest que usaremos para crear la petición. A esta función la llamaré dameXMLHttpRequest. No todos los navegadores utilizan la petición de la misma manera y no todos los navegadores soportan AJAX, es por esta razón que se necesita hacer una pequeña validación y obtener el AJAX dependiendo del navegador.
function dameXMLHttpRequest()
{
if(window.XMLHttpRequest) // Navegadores actuales
return new XMLHttpRequest();
else if(window.ActiveXObject) // Navegadores antiguos como IE6
return new ActiveXObject("Microsoft.XMLHTTP");
else // Si no soporta AJAX
return null;
}
Luego declararé una variable global llamada httpRequest que será la que usaremos para la petición. La declaro de forma global para que se pueda utilizar en la función que manda la petición y en la que procesa el resultado.
var httpRequest = null;
Luego implementaré la función llamada muestraContenido que procesará la información obtenida de la petición AJAX y mostrará en pantalla el resultado. Solo se mostrará el contenido si la petición ya terminó (readyState == 4) y si se terminó satisfactoriamente (status == 200).
function muestraContenido()
{
if(httpRequest.readyState == 4) // 4 = completado
{
if(httpRequest.status == 200) // 200 = OK
{
// Obtenemos el div con id="contenido"
// Diferentes navegadores utilizan diferentes
// formas de obtener los elementos HTML
var cont = null;
if (document.all)
cont = document.all["contenido"];
else if (document.getElementById)
cont = document.getElementById("contenido");
// Si se pudo obtener el div contenido le colocamos
// el resultado de la peticion.
if (cont)
cont.innerHTML = httpRequest.responseText;
}
}
}
Luego implementaré una función que reciba como parámetro la página que se desea obtener A, B o C y de acuerdo a eso mande la petición a la página correspondiente. A esta función la llamaré peticionAJAX.
function peticionAJAX( pag )
{
// Obtenemos el objeto XMLHttpRequest
httpRequest = dameXMLHttpRequest();
// Verificamos que AJAX este soportado
if (httpRequest == null) return;
// Asignamos el evento que se ejecutará cuando
// la petición haya terminado.
httpRequest.onreadystatechange = muestraContenido;
// Preparamos la pagina de destino
if (pag == 'A')
httpRequest.open('GET', 'http://localhost/pagA.html', true);
else if (pag == 'B')
httpRequest.open('GET', 'http://localhost/pagB.html', true);
else
httpRequest.open('GET', 'http://localhost/pagC.html', true);
// Enviamos la peticion
httpRequest.send(null);
}
Por último agregaré la invocación a cada uno de los botones de tal forma que cuando le hagamos clic se realice la petición correspondiente.
<input type="button" value="Dame A" onclick="peticionAJAX('A');" />
<input type="button" value="Dame B" onclick="peticionAJAX('B');"/>
<input type="button" value="Dame C" onclick="peticionAJAX('C');" />
Todas las funciones de Javascript las colocaremos dentro de tags <script> pero podrías agregarlo a través de un enlace a un archivo javascript. El código completo se debería ver algo así:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Primera prueba con AJAX</title>
<script>
function dameXMLHttpRequest()
{
if(window.XMLHttpRequest) // Navegadores actuales
return new XMLHttpRequest();
else if(window.ActiveXObject) // Navegadores antiguos como IE6
return new ActiveXObject("Microsoft.XMLHTTP");
else // Si no soporta AJAX
return null;
}
var httpRequest = null;
function muestraContenido()
{
if(httpRequest.readyState == 4) // 4 = completado
{
if(httpRequest.status == 200) // 200 = OK
{
// Obtenemos el div con id="contenido"
// Diferentes navegadores utilizan diferentes
// formas de obtener los elementos HTML
var cont = null;
if (document.all)
cont = document.all["contenido"];
else if (document.getElementById)
cont = document.getElementById("contenido");
// Si se pudo obtener el div contenido le colocamos
// el resultado de la peticion.
if (cont)
cont.innerHTML = httpRequest.responseText;
}
}
}
function peticionAJAX( pag )
{
// Obtenemos el objeto XMLHttpRequest
httpRequest = dameXMLHttpRequest();
// Verificamos que AJAX este soportado
if (httpRequest == null) return;
// Asignamos el evento que se ejecutará cuando
// la petición haya terminado.
httpRequest.onreadystatechange = muestraContenido;
// Preparamos la pagina de destino
if (pag == 'A')
httpRequest.open('GET', 'http://localhost/pagA.html', true);
else if (pag == 'B')
httpRequest.open('GET', 'http://localhost/pagB.html', true);
else
httpRequest.open('GET', 'http://localhost/pagC.html', true);
// Enviamos la peticion
httpRequest.send(null);
}
</script>
</head>
<body>
<div style="border:1px solid #ddd; background-color:#eee; text-align:center;">
<input type="button" value="Dame A" onclick="peticionAJAX('A');" />
<input type="button" value="Dame B" onclick="peticionAJAX('B');"/>
<input type="button" value="Dame C" onclick="peticionAJAX('C');" />
</div>
<div id="contenido" style="text-align:center;">
Aun no hay contenido. Presione algun boton.
</div>
</body>
</html>
Listo!! Ahora prueba tu página web en http://localhost/ajax.html para que veas cómo aparece el contenido de cada petición en la parte del contenido.
Mejorando el lado cliente
A pesar de que nuestras peticiones AJAX ya funcionan, podemos notar que el único que se ve bien (para el usuario) es el resultado del botón A debido a que el resultado ya viene en formato HTML. Para mejorar esto vamos a agregar dos funciones (para B y C) que procesen el resultado recibido y le den el formato correcto.
La función muestraContenidoParaB
Esta función muestraContenidoParaB es muy parecida a la original, con la diferencia que no asignará el contenido de forma directa sino que separará el contenido utilizando un split por comas y creará de forma dinámica la tabla.
Para efectos prácticos solo muestro la parte dónde ha habido un cambio a partir de la función muestraContenido.
function muestraContenidoParaB()
{
// Ver funcion muestraContenido
// Si se pudo obtener el div contenido le colocamos
// el resultado de la peticion.
if (cont)
{
var partes = httpRequest.responseText.split(",");
var html = "<table border='2'><tr>";
for (i=0; i<partes.length; i++)
{
if (i % 3 == 0 && i != 0)
html += "</tr><tr>";
if (i < 3) // 3 columnas
html += "<th>" + partes[i] + "</th>";
else
html += "<td>" + partes[i] + "</td>";
}
html += "</tr></table>";
cont.innerHTML = html;
}
// Ver funcion muestraContenido
}
La gran ventaja de utilizar este método es que la cantidad de datos que viaja por la web al momento de la petición es bastante menor que el caso del botón A que envía todo el HTML. En este caso solo mandamos los datos haciendo que la petición sea más rápida.
La función muestraContenidoParaC
Esta función muestraContenidoParaC es muy parecida a la anterior, con la diferencia que no necesitamos hacer un split a los datos ya que vienen en JSON el cual es interpretado muy facilmente por Javascript y es convertido a un objeto con solo utilizar el comando eval de javascript. Esto facilita bastante la manipulación de datos.
Para efectos prácticos solo muestro la parte dónde ha habido un cambio a partir de la función muestraContenido.
function muestraContenidoParaC()
{
// Ver funcion muestraContenido
// Si se pudo obtener el div contenido le colocamos
// el resultado de la peticion.
if (cont)
{
var filas = eval("{" + httpRequest.responseText + "}");
var html = "<table border='3'>";
for (i = 0; i < filas.length; i++)
{
html += "<tr>";
for (k = 0; k < filas[i].length; k++)
{
if (i == 0) // primera fila
html += "<th>" + filas[i][k] + "</th>";
else
html += "<td>" + filas[i][k] + "</td>";
}
html += "</tr>";
}
html += "</table>";
cont.innerHTML = html;
}
// Ver funcion muestraContenido
}
Debes tener en cuenta que utilizar eval de forma directa no es recomendado por no ser muy seguro y dar cierta vulnerabilidad a tu página. Hay formas de evitar utilizar eval y usar parsers de JSON pero para la mayoría de casos con eval basta.
Adicionalmente, tienes que redirigir el evento de forma correcta para cada uno de las peticiones, es decir, para la petición A el evento que procesa el resultado es el muestraContenido pero para B y C son muestraContenidoParaB y muestraContenidoParaC respectivamente.
Para esto lo que tienes que hacer es modificar el método peticionAJAX para que asigne el evento onreadystatechange de forma correcta.
El código completo de la página ajax.html te lo muestro a continuación:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Primera prueba con AJAX</title>
<script>
function dameXMLHttpRequest()
{
if(window.XMLHttpRequest) // Navegadores actuales
return new XMLHttpRequest();
else if(window.ActiveXObject) // Navegadores antiguos como IE6
return new ActiveXObject("Microsoft.XMLHTTP");
else // Si no soporta AJAX
return null;
}
var httpRequest = null;
function muestraContenido()
{
if(httpRequest.readyState == 4) // 4 = completado
{
if(httpRequest.status == 200) // 200 = OK
{
// Obtenemos el div con id="contenido"
// Diferentes navegadores utilizan diferentes
// formas de obtener los elementos HTML
var cont = null;
if (document.all)
cont = document.all["contenido"];
else if (document.getElementById)
cont = document.getElementById("contenido");
// Si se pudo obtener el div contenido le colocamos
// el resultado de la peticion.
if (cont)
cont.innerHTML = httpRequest.responseText;
}
}
}
function muestraContenidoParaB()
{
if(httpRequest.readyState == 4) // 4 = completado
{
if(httpRequest.status == 200) // 200 = OK
{
// Obtenemos el div con id="contenido"
// Diferentes navegadores utilizan diferentes
// formas de obtener los elementos HTML
var cont = null;
if (document.all)
cont = document.all["contenido"];
else if (document.getElementById)
cont = document.getElementById("contenido");
// Si se pudo obtener el div contenido le colocamos
// el resultado de la peticion.
if (cont)
{
var partes = httpRequest.responseText.split(",");
var html = "<table border='2'><tr>";
for (i=0; i<partes.length; i++)
{
if (i % 3 == 0 && i != 0)
html += "</tr><tr>";
if (i < 3) // 3 columnas
html += "<th>" + partes[i] + "</th>";
else
html += "<td>" + partes[i] + "</td>";
}
html += "</tr></table>";
cont.innerHTML = html;
}
}
}
}
function muestraContenidoParaC()
{
if(httpRequest.readyState == 4) // 4 = completado
{
if(httpRequest.status == 200) // 200 = OK
{
// Obtenemos el div con id="contenido"
// Diferentes navegadores utilizan diferentes
// formas de obtener los elementos HTML
var cont = null;
if (document.all)
cont = document.all["contenido"];
else if (document.getElementById)
cont = document.getElementById("contenido");
// Si se pudo obtener el div contenido le colocamos
// el resultado de la peticion.
if (cont)
{
var filas = eval("{" + httpRequest.responseText + "}");
var html = "<table border='3'>";
for (i = 0; i < filas.length; i++)
{
html += "<tr>";
for (k = 0; k < filas[i].length; k++)
{
if (i == 0) // primera fila
html += "<th>" + filas[i][k] + "</th>";
else
html += "<td>" + filas[i][k] + "</td>";
}
html += "</tr>";
}
html += "</table>";
cont.innerHTML = html;
}
}
}
}
function peticionAJAX( pag )
{
// Obtenemos el objeto XMLHttpRequest
httpRequest = dameXMLHttpRequest();
// Verificamos que AJAX este soportado
if (httpRequest == null) return;
// Preparamos la pagina de destino
if (pag == 'A')
{
httpRequest.onreadystatechange = muestraContenido;
httpRequest.open('GET', 'http://localhost/pagA.html', true);
}
else if (pag == 'B')
{
httpRequest.onreadystatechange = muestraContenidoParaB;
httpRequest.open('GET', 'http://localhost/pagB.html', true);
}
else
{
httpRequest.onreadystatechange = muestraContenidoParaC;
httpRequest.open('GET', 'http://localhost/pagC.html', true);
}
// Enviamos la peticion
httpRequest.send(null);
}
</script>
</head>
<body>
<div style="border:1px solid #ddd; background-color:#eee; text-align:center;">
<input type="button" value="Dame A" onclick="peticionAJAX('A');" />
<input type="button" value="Dame B" onclick="peticionAJAX('B');"/>
<input type="button" value="Dame C" onclick="peticionAJAX('C');" />
</div>
<div id="contenido" style="text-align:center;">
Aun no hay contenido. Presione algun boton.
</div>
</body>
</html>
El mismo ejemplo con PHP
Ahora te voy a mostrar como utilizar AJAX con PHP para que no tengas que crear contenido estático sino que puedas generar contenido dinámico.
Como PHP es dinámico lo voy a programar todo en un solo archivo llamado ajax_php.php. Este archivo procesará las peticiones y servirá como punto de entrada al igual como la página ajax.html en el caso anterior.
Lo primero que voy a hacer es programar las páginas A, B y C. La idea es que cuando el usuario ingrese a http://localhost/ajax_php.php?pag=A proporcionemos la página A, http://localhost/ajax_php.php?pag=B proporcionemos la página B y http://localhost/ajax_php.php?pag=C proporcionemos la página C.
Supongo que te has dado cuenta que en realidad la parte que dice ?pag=A en el url es un parámetro, es decir, a la página web ajax_php.php le estamos mandando un parámetro llamado pag con valor A. A estos parámetros se les conoce como los parámetros GET y se almacenan de forma automática dentro de la variable global $_GET de PHP.
Al inicio detecto si se ha solicitado una página A, B o C. Si este es el caso entonces obtengo los datos que quiero mostrar como resultado (en este caso es un arreglo estático pero podrían ser los resultados de una base de datos o un archivo) y los muestro según el tipo. Una vez mostrados los datos me aseguro que no siga corriendo el script llamando al comando exit.
Si no se solicitó una página entonces muestro el html equivalente al ajax.html del ejemplo anterior con la única modificación de que ahora todas las peticiones se hacen a ajax_php.php utilizando la letra presionada como parámetro. En realidad lo único que cambia es la función peticionAjax.
El código completo del archivo ajax_php.php es el siguiente:
<?php
if (isset($_GET["pag"]))
{
$datos = array(
array("ID", "MARCA", "PRECIO"),
array("456", "Invalida", "10.55"),
array("378", "Percha", "11.33"),
array("326", "Marcon", "7.55")
);
$pag = $_GET["pag"];
if ($pag == "A")
{
$tag = "th";
echo "<table border='1'>";
foreach ($datos as $fila)
{
echo "<tr>";
foreach ($fila as $celda)
echo "<$tag>$celda</$tag>";
echo "</tr>";
$tag = "td";
}
echo "</table>";
exit();
}
else if ($pag == "B")
{
for ($i=0; $i<count($datos); $i++)
{
if ($i != 0) echo ",";
echo implode(",", $datos[$i]);
}
exit();
}
else if ($pag == "C")
{
echo json_encode($datos);
exit();
}
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Primera prueba con AJAX</title>
<script>
function dameXMLHttpRequest()
{
if(window.XMLHttpRequest) // Navegadores actuales
return new XMLHttpRequest();
else if(window.ActiveXObject) // Navegadores antiguos como IE6
return new ActiveXObject("Microsoft.XMLHTTP");
else // Si no soporta AJAX
return null;
}
var httpRequest = null;
function muestraContenido()
{
if(httpRequest.readyState == 4) // 4 = completado
{
if(httpRequest.status == 200) // 200 = OK
{
// Obtenemos el div con id="contenido"
// Diferentes navegadores utilizan diferentes
// formas de obtener los elementos HTML
var cont = null;
if (document.all)
cont = document.all["contenido"];
else if (document.getElementById)
cont = document.getElementById("contenido");
// Si se pudo obtener el div contenido le colocamos
// el resultado de la peticion.
if (cont)
cont.innerHTML = httpRequest.responseText;
}
}
}
function muestraContenidoParaB()
{
if(httpRequest.readyState == 4) // 4 = completado
{
if(httpRequest.status == 200) // 200 = OK
{
// Obtenemos el div con id="contenido"
// Diferentes navegadores utilizan diferentes
// formas de obtener los elementos HTML
var cont = null;
if (document.all)
cont = document.all["contenido"];
else if (document.getElementById)
cont = document.getElementById("contenido");
// Si se pudo obtener el div contenido le colocamos
// el resultado de la peticion.
if (cont)
{
var partes = httpRequest.responseText.split(",");
var html = "<table border='2'><tr>";
for (i=0; i<partes.length; i++)
{
if (i % 3 == 0 && i != 0)
html += "</tr><tr>";
if (i < 3) // 3 columnas
html += "<th>" + partes[i] + "</th>";
else
html += "<td>" + partes[i] + "</td>";
}
html += "</tr></table>";
cont.innerHTML = html;
}
}
}
}
function muestraContenidoParaC()
{
if(httpRequest.readyState == 4) // 4 = completado
{
if(httpRequest.status == 200) // 200 = OK
{
// Obtenemos el div con id="contenido"
// Diferentes navegadores utilizan diferentes
// formas de obtener los elementos HTML
var cont = null;
if (document.all)
cont = document.all["contenido"];
else if (document.getElementById)
cont = document.getElementById("contenido");
// Si se pudo obtener el div contenido le colocamos
// el resultado de la peticion.
if (cont)
{
var filas = eval("{" + httpRequest.responseText + "}");
var html = "<table border='3'>";
for (i = 0; i < filas.length; i++)
{
html += "<tr>";
for (k = 0; k < filas[i].length; k++)
{
if (i == 0) // primera fila
html += "<th>" + filas[i][k] + "</th>";
else
html += "<td>" + filas[i][k] + "</td>";
}
html += "</tr>";
}
html += "</table>";
cont.innerHTML = html;
}
}
}
}
function peticionAJAX( pag )
{
// Obtenemos el objeto XMLHttpRequest
httpRequest = dameXMLHttpRequest();
// Verificamos que AJAX este soportado
if (httpRequest == null) return;
// Preparamos la pagina de destino
httpRequest.open('GET', 'http://localhost/ajax_php.php?pag=' + pag, true);
// Asignamos el evento correcto
if (pag == 'A')
httpRequest.onreadystatechange = muestraContenido;
else if (pag == 'B')
httpRequest.onreadystatechange = muestraContenidoParaB;
else
httpRequest.onreadystatechange = muestraContenidoParaC;
// Enviamos la peticion
httpRequest.send(null);
}
</script>
</head>
<body>
<div style="border:1px solid #ddd; background-color:#eee; text-align:center;">
<input type="button" value="Dame A" onclick="peticionAJAX('A');" />
<input type="button" value="Dame B" onclick="peticionAJAX('B');" />
<input type="button" value="Dame C" onclick="peticionAJAX('C');" />
</div>
<div id="contenido" style="text-align:center;">
Aun no hay contenido. Presione algun boton.
</div>
</body>
</html>
Consideraciones
El código que hemos presentado no tiene como objetivo ser perfecto sino enseñar cómo funciona AJAX. Si quieres hacer una página web que utilice AJAX deberías tener en cuenta lo siguiente:
- Todo lo que puede fallar va a fallar. Con esto te quiero decir que siempre tienes que validar todo ya que cualquier cosa puede fallar. En este ejemplo lo más probable que falle es la petición AJAX, es decir, que el servidor se caiga y no me devuelva ningún resultado. Para controlar esto necesitas revisar el status de la petición y mostrarle al usuario un error conveniente.
- No muestra el progreso o una imagen que simule que se está procesando los datos.
- No manejamos errores en cuanto a la información obtenida. Siempre suponemos que es correcta.
- No encriptamos la información recibida. Si necesitas transmitir información de forma segura deberías encriptarla.
- No ofrecemos una opción para abortar la petición que sería útil para el usuario que no quiere esperar mucho tiempo a que cargue la aplicación.
- Hay un tercer tipo de XMLHttpRequest (ActiveXObject MSXML2.XMLHTTP) que no hemos intentado obtener en la función dameXMLHttpRequest.
- No he optimizado el código y he repetido muchas veces pedazos de código que debería haber podido llevar a funciones.
Para poder solucionar todos estos problemas te recomiendo que averigues más acerca de XMLHttpRequest.

Hola, muy bien explicado…..felicitaciones….Te envío un cordial saludo desde Santiago de Chile..
Wow, Muchas Gracias, es la mejor explicacion de Ajax, e buscado por todas partes, pero todos, te dan la parte de codigo, y no te dicen ni estructura ni nda, ahora ya se como va y entiendo mas, claro, voy a seguir estudiando. Muchas GRacias….
Amigo… Hace tiempo me consegui un libro llamado “Ajax: Un juego de niños”, e intente una aplicacion ajax que habia ahi, la primera y mas sencilla, y no me funciono, y encontre la tuya e intente hacerle varios cambios, pero no me funcionaba ninguno… Y veia todos los detallitos hasta que vi que tu habias escrito “onreadystatechange” pero en el libro era “onreadyStateChange” y le cambie esas letras mayusculas, y listo, santo remedio, hace apenas 5 minutos que me funciono y de verdad estoy feliz, gracias amigo porque de no haber sido por tu post no me habria dado cuenta de que el error eran 2 benditas letras mayusculas!!! Gracia amigo, tu post me salvo la vida!!!
Q barbaro este tuto muy bien esplicado, te comentare el problema q tenia y me salvasteee. Es que queria llenar dos combos dinamicamente desde mysql usando Java JSP pero habia encontrado una solucion pero la lib prototype me hacia clavo con la lib jquery y ocupa dos apis de google entonces la solucion que encontraba no me funcionaba asi q toko buscarme otra manera de llenar los combos con ajax porq la que usaba me daba problema asi que lei tu tuto y lo trate de implementar en mi codigo y me funko d maravillaaaaaa. Gracias amigoooo!!!