Disectando XMLHttpRequest
Intro
Hace mucho, mucho tiempo atrás, comenté sobre los diversos métodos para recoger información desde el servidor sin recargar la página. Ocupé el término RPC vía HTTP para dar cuenta de este fenómeno, pero desde el artículo de Adaptative Path llamado ajax: a new approach to web applications, el nombre Ajax se ha incrustado en el inconsciente colectivo de todos nosotros.
Como bien dice nuestro estimado James, Ajax es un enfoque, más que una tecnología específica, que tiene como antecedente trucos tan sucios como recoger información en iframes escondidos, tal como lo hace mi querido jsrs. Ok, ok, hasta ahora no estoy diciendo nada que no haya dicho, pero sirve de introducción
Breve explicación de como funciona HTTP
Recordemos, ante que nada, que la WWW funciona con un modelo de cliente-servidor, siendo el cliente el navegador (Firefox, Mozilla, Opera o el engendro) y el servidor un demonio http (Apache, Zeus y el otro engendro).
En una carga de página normal, el cliente envía lo que se llama una petición al servidor. Cuando ponemos en la barra del navegador "http://php.apsique.com", enviamos el siguiente texto al servidor por un puerto, que generalmente es el 80:
GET / HTTP/1.0
Como vemos en la especificación del protocolo HTTP, existen diversos métodos a través de los cuales podemos decir al servidor que tipo de petición debemos hacer. Tenemos los clásicos GET Y POST, pero también otros como HEAD, DELETE y PUT. Lo importante es recordar que GET sirve para recuperar información sin alterar la fuente, en tanto que POST nos permite entregar información que altera el recurso.
El servidor, al recibir una petición, nos entrega una respuesta, que es también un texto. Esta respuesta siempre comienza con un código, que indica el estado de la operación. Entre ellos tenemos el esperado 200 (todo ok), 301 (movido permanentemente) y los temidos 403 (prohibido), 404 (no existe recurso) y 500 (error del cgi). Después de esta respuesta, generalmente se ofrece el tipo MIME del contenido (texto, xml, imagen) y el contenido propiamente tal. Por ejemplo, para una página típica de mi sitio
Date: Mon, 30 May 2005 07:12:49 GMT Server: Apache/1.3.33 (Unix) (Gentoo/Linux) mod_ruby/1.2.4 Ruby/1.8.2(2004-12-25) PHP/4.3.11 X-Powered-By: PHP/4.3.11 Keep-Alive: timeout=15, max=100 Connection: Keep-Alive Transfer-Encoding: chunked Content-Type: text/html; charset=utf-8 200 OK
A estas alturas del partido, si no han abandonado, se preguntarán porque les estoy dando tanto la lata. La respuesta es simple: si bien en una carga de página normal todo este enredo lo manejan de forma casi mágica el cliente y el servidor de forma automática, al ocupar Ajax hay que manejar todo esto, en el fondo, a mano. Si bien ya existen bastantes aplicaciones que ocultan esta información, si no tienen claro el proceso de consulta y respuesta, no van a poder entender bien como funciona el proceso en realidad y de donde surgen los errores.
Ajax
Ya teniendo en nuestras cabezas el proceso de consulta-respuesta, podemos empezar a trabajar en Ajax. Si quieren un texto muy bueno, y en el cual se basará la discusión, lean Using the XML HTTP Request object
El nombre Ajax es un acrónimo de "Asynchronous JavaScript + XML". Ahora, no es necesario ocupar XML. Si, tal como lo oyeron. Si bien siempre suena bonito ocupar esta siglita, la verdad es que la consulta y recepción son simples textos; así, si bien se puede ocupar XML para ordenar la cosa, no estamos limitados por ello.
Javascript al mando
A partir del Explorer 6 (si no me equivoco) y de Mozilla 1.6, tenemos a nuestra disposición el objeto XMLHttpRequest. El problemita es que en IE (para variar) se accede a el con
new ActiveXObject("Msxml2.XMLHTTP") o new ActiveXObject("Microsoft.XMLHTTP") dependiendo de la versión del IE. Por tanto, lo mejor es crear una función que nos entregue el objeto, la cual diría algo como:
- function get_xmlhttp() {
- try {
- xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
- } catch (e) {
- try {
- xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
- } catch (E) {
- xmlhttp = false;
- }
- }
- if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
- xmlhttp = new XMLHttpRequest();
- }
- return xmlhttp
- }
Una vez que tenemos el objeto, para hacer una petición debemos abrir la conexión y enviar la consulta. Para ello utilizados
- xmlhttp.open(metodo, url,async);
- xmlhttp.send(contenido);
Recuerden que si utilizamos "GET", bastará con poner las variables en el url, en el clásico formato
script.php?variable1=valor1&variable2=valor2
Escapando los carácteres extraños con encodeURIComponent. Si ocupan POST, deben enviar el contenido en la variable contenido en send, aunque por ahora no sé muy bien como se hace (apenas tenga el dato, aviso)
Normalmente, nosotros deseamos saber en que momento el servidor nos entrega la respuesta y realizar una función con ésta. Para ello, existe una función de xmlhttp llamada onreadystatechange, la cual se ejecuta cada vez que cambia el estado de la conexión. Sabiendo que la propiedad readyState se pone a 4 cuando la respuesta ha sido recibida, podemos mejorar el código haciendo
- xmlhttp.open(metodo, url,async);
- xmlhttp.onreadystatechange=function() {
- if (xmlhttp.readyState==4) {
- callback(xmlhttp)
- }
- }
- xmlhttp.send(null)
callback es el nombre de una función que recibirá el resultado de la llamada al servidor
Si revisamos el objeto xmlhttp una vez recibida la respuesta, veremos que cuenta con los siguientes métodos de interés
- getAllResponseHeaders()
- Nos entrega todas las cabeceras de respuesta desde el servidor
- status
- El código de estatus de la petición (normalmente, 200)
- responseText
- Texto literal de la respuesta
- responseXML
- Objeto XMLDocument, el cual se puede analizar con las funciones de DOM típicas, como getElementById y similares.De aquí la X de Ajax
El servidor
Desde el lado del servidor, la cosa es muy sencilla. Podemos enviar las cabeceras que queramos, así como el texto que se nos antoje. Por ejemplo, podemos utilizar el código 304 para decir que la página no ha tenido actualización desde la última vez que se visitó
Un dato importante es que solamente si definimos el tipo de contenido como xml con
Content-type: text/xml
La propiedad responseXML tendrá un valor en el objeto xmlhttp
Ejemplo
Esa sería la teoría del asunto, mis estimados. Ahora, nada mejor que un buen ejemplo para que vean el bicho en operaciones. Como siempre, pueden encontrar los archivos como adjunto al final del post
Estatus
Nada por ahora
Cabecera
Nada por ahora
Cuerpo
Nada por ahora
Propiedades y métodos objeto xmlhttprequest
Nada por ahora
| Adjunto | Tamaño |
|---|---|
| xhttprequest.zip | 1.55 KB |
- 7758 lecturas

Por cierto - y no es que pretenda autopromocionarme - ¿leíste el artículo sobre Ajax que escribí hace un tiempo?...
http://www.mouse.cl/2005/rep/04/15/index.asp
Quizá sirva para quienes no se han interiorizado en el tema ;)
¡Salute!
Simpático artículo, mi estimado. Gracias por el link :)
Por lo menos desde mi óptica, trabajar en Ajax, en HTTP-RPC o como quieran llamarlo no es tan complicado, si sabes lo que estás haciendo. Claro, hay que saber un poco más de lo requerido para trabajar con un sistema clásico de cgi, pero el esfuerzo vale la pena.
Y a todo esto, feliz cumpleaños. Podrías ponerte un avatar, para identificarte rápido...
Estimados:
Si han ocupado IE para ver el ejemplo de este artículo, les lanzará un error de javascript. El error fue olvidarme de poner "var" para "valor" y "xml" al buscar los valores de los input. En firefox funciona sin problemas. Mil perdones.
En la noche espero tener corregido el error, que de verdad es mínimo. Por ahora, el zip con los archivos para probar en el servidor de cada cual está corregido.
Actualización:Acabo de llegar y corregí el error. Debería funcionar en el engendro.
Objetivo
Al finalizar este artículo, el lector, si ha entendido algo, será capaz de
Ok, ok, me equivoqué. No se debe ocupar
escapepara enviar las variables, sinoencodeURLComponent. Hay que ver como funciona en IE.Lei el comentario y me parece algo excelente que alguien se preocuope por subir estos comentarios a la red, ya que los que empezamos a programar con estas tecnologias nos damos una idea mas amplia de realizar nuestros trabajos de una manera eficiente.
Gracias
He probado el objeto ajax, pero la unica falla k le encontre fue k no me deja mandar archivos en un formulario, es con lo unico k he tenido problemas, pero el resto de cosas, la raja. Si alguien ha intentado mandar archivos y le resulto por favor avise.
Mil gracias por tu articulo, la verdad es que me he leido como 20.. en un ratito, me has sacado de sendos apuros.
Tienes una forma muy peculiar de explicar las cosas tks ^^
De nada.
Mientras más me explico, más me complico.
Enviar un comentario nuevo