Publicidad:
La Coctelera

Garbage In, Garbage Out

Diseño web, tecnología, e internet.

11 Octubre 2005

AJAX: EL objeto XMLHttpRequest

Como me está picando la curiosidad de entender esto de AJAX, he decidido echar un vistazo a algún tutorial básico sobre AJAX y entender cómo demonios se puede recorrer un documento XML con Javascript, teniendo en cuenta que implementar y enviar un parser de XML en Javascript al navegador es muy costoso.

El secreto, que yo no conocía, es que se ha implementado, en los navegadores más utlizados (Internet Explorer, Firefox, etc.), un objeto XMLHttpRequest que se encarga de todo esto. Es decir, que basta con crear una instancia de este objeto para poder realizar peticiones HTTP al servidor en XML y recibir sus respuestas de modo asíncrono o síncrono.

Aunque siempre he criticado a Microsoft por ser unos copiones y por crear productos cerrados para atar al cliente, esta vez debo darles la enhorabuena por ser los primeros en crear este objeto que va a dar lugar a una nueva era de aplicaciones web nunca vistas hasta ahora. De todas formas, todavía debo seguir criticándoles su manía de crear tecnologías exclusivas para su navegador Internet Explorer, ya que la forma de crear instancias de este objeto es exclusivo para sistemas Windows, y por tanto diferente de otros navegadores que tratan de ser multiplataforma.

Comencemos.

La forma de crear una instancia de este objeto en cualquier navegador es:

var req = new XMLHttpRequest();

y en Microsoft Internet Explorer depende de ActiveX:

var req = new ActiveXObject("Microsoft.XMLHTTP");

Métodos

Los métodos de un objeto XMLHttpRequest son los siguientes:

  • abort(): Aborta la petición actual.
  • getAllResponseHeaders(): Devuelve todas las cabeceras (etiquetas y valores) como un string.
  • getResponseHeader("headerLabel"): Devuelve el valor de la cabecera etiquetada como headerLabel.
  • open("method", "URL"[, asyncFlag[, "userName"[, "password"]]]): Abre una conexión a una URL, con un método HTTP (get o post), y otros parámetros opcionales.
  • send(content): Envía la petición. Suele ser un String o un objeto DOM
  • setRequestHeader("label", "value"): Crea un par etiqueta/valor para ser enviado en la cabecera de la petición.

Los métodos más importantes son open y send.

El método open prepara la conexión con el servidor. Para ello se le pasa la URL - absoluta o relativa - y el método HTTP, get o post, según si se recibe o se envía datos.

Por defecto, la conexión es asíncrona, es decir, la petición se realiza al servidor y el usuario puede seguir interactuando con la página sin que se dé cuenta. Si se quiere una conexión síncrona, se debe utilizar el parámetro asyncFlag=false, lo que hará que el navegador quede parado hasta recibir la respuesta del servidor. Esto es peligroso porque puede dejar colgado al navegador si hay algún tipo de error, por lo que se aconseja siempre utilizar conexiones asíncronas.

Propiedades

Las propiedades del objeto XMLHttpRequest son las siguientes:

  • onreadystatechange: Guarda el nombre de la función Javascript que manejará los cambios de estado en la petición.
  • readyState: Entero que codifica el estado actual de la petición
    • 0 = No Inicializado
    • 1 = Cargando
    • 2 = Cargado
    • 3 = Interactuando
    • 4 = Completado
  • responseText: Versión en forma de String de los datos devueltos por el servidor.
  • responseXML: Objeto DOM compatible de la respuesta del servidor.
  • status: Código de estado devuelto por el servidor, como 404 para No encontrado o 200 para Ok.
  • statusText: Mensaje que acompaña al código de estado.

De estas propiedades, las más importantes on onreadystatechange, readyState, y la respuesta responseText / responseXML.

La primera, onreadystatechange, sirve para asociar el método Javascript que hayamos escrito para gestionar los cambios de estado de la petición. Es decir, como es una comunicación asíncrona, se necesita tener un método implmentado por nosotros que gestione los diferentes eventos, como por ejemplo, la llegada de la respuesta. Esta es la propiedad que sirve para decirle a XMLHttpRequest el nombre de ese método.

La segunda, readyState, es un número que informa del estado de la petición. El estado más interesante es el número 4, que recoge el momento en el que llega la respuesta del servidor para poder procesarla.

La respuesta viene en dos versiones diferentes: Una en un texto normal, almacenada en la propiedad responseText; y otra en un objeto estándar DOM, almacenado en la propiedad responseXML. Lógicamente, el medio más poderoso de procesar las respuesta, es mediante el objeto DOM, ya que puede ser recorrido a través de los métodos estandarizados por la W3C DOM. Date cuenta que este DOM es un documento en XML, no en HTML.

Código general

Sabiendo todo esto, podemos crear una función genérica para realizar una petición:

var req;

function loadXMLDoc(url) {
    req = false;
    //  parte para cualquier navegador
    if(window.XMLHttpRequest) {
        try {
            req = new XMLHttpRequest();
        } catch(e) {
            req = false;
        }
    // parte para Internet Explorer / ActiveX
    } else if(window.ActiveXObject) {
        try {
         req = new ActiveXObject("Msxml2.XMLHTTP");
       } catch(e) {
            try {
               req = new ActiveXObject("Microsoft.XMLHTTP");
             } catch(e) {
                   req = false;
                    }
                }
        }
        if(req) {
            req.onreadystatechange = processReqChange;
            req.open("GET", url, true);
            req.send("");
    }
}

Y otra función para procesar las respuestas:

function processReqChange() {
    if (req.readyState == 4) {
        if (req.status == 200) {
            // ...Aquí irían la lógica necesaria
        } else {
            alert("Error recibiendo datos XML:\n" +
                req.statusText);
        }
    }
}

Seguridad

Por motivos de seguridad, no se puede acceder a los ficheros locales a través del protocolo file:// sin tener que lidiar con configuraciones. Debido a esto no se pueden hacer test de páginas locales directamente, y lo mejor es instalar un servidor HTTP como Apache y hacer conexiones http://localhost/.

También, el dominio de la dirección del servidor ha de ser el mismo que el de la página que contiene el script que realiza la petición.

Un ejemplo sencillo

Un ejemplo sencillo que he mirado para entender la idea básica de todo esto es el que proporciona Apple. Se trata de una página sencilla que utiliza los RSS de iTunes para cargar unas listas. Mira el código fuente, y verás que es fácil de entender.

Nada más. Espero que este artículo haya servido para que tanto tú como yo nos iniciemos en esto de AJAX.

Artículos (en inglés) que he leído para entender esto:

servido por gigo 7 comentarios compártelo

7 comentarios · Escribe aquí tu comentario

gringo

gringo dijo

*clap* *clap* *clap* ... ( aplausos ) excelente la información que haz publicado... ya mismo lo estoy imprimiendo para ponerme a jugar con esto...

mil gracias...

14 Octubre 2005 | 06:23 AM

gigo

gigo dijo

Gracias. Ya que leo, pues escribo. Espero te sirva para algo.

14 Octubre 2005 | 07:58 AM

Daniel

Daniel dijo

Gracias, es lo que estaba buscando

15 Mayo 2006 | 08:26 PM

Maki

Maki dijo

Muy buen tutorial. Pero tengo una pregunta, si queremos mostrar la informacion de una pagina que no este en el host como lo hariamos¿?

req.open("post", "www.prueba.com/prueba.php", true);

daria un error en req.open, por poner una direccion que no pertenece a nuestro host. como los solucionariamos ¿? Por favor mandeme un mail

12 Junio 2006 | 08:02 PM

Fernando Garza

Fernando Garza dijo

para hacer eso puedes apuntar a una dirección en el mismo servidor pero que el documento XML sea generado por un script de lado del servidor, por ej. Perl o PHP, y que ése srcipt recoja datos de otro servidor, y así podrías engañar al objeto XMLHttpRequest.

25 Julio 2006 | 08:02 PM

Alex Sancho

Alex Sancho dijo

Ademas de la tecnica que comenta Fernando, que basicamente se trata de crear un "proxy" en algun lenguaje adicional, tambien podemos utilizar "mod_proxy" para crear llamadas locales, que internamente sean redirigidas a otro servidor, engañando asi al navegador.

ProxyPass /ajax.php http://example.com/ajax.php
ProxyPassReverse /ajax.php http://example.com/ajax.php

Salu2

26 Julio 2006 | 11:36 AM

Miguel

Miguel dijo

Bueno y si sólo quiero mostrar partes del código que recibo en responseXML o responseText? Cómo tendría que haecr?

6 Noviembre 2006 | 03:01 PM

Escribe tu comentario


Sobre mí

Avatar de gigo

Garbage In, Garbage Out

ver perfil »
contacto »
Desarrollador web con ganas de aprender y enseñar, porque aún queda mucho por aprender y por enseñar. Uso esta bitácora para hacer mis apuntes profesionales y de paso contribuir a ayudar a mis compañeros de, ésta, mi profesión. [guiño]

Sindicación

Fotos

gigo todavía no ha subido ninguna foto.

¡Anímale a hacerlo!

Buscar

suscríbete

Selecciona el agregador que utilices para suscribirte a este blog (también puedes obtener la URL de los feeds):

¿Qué es esto?

Crea tu blog gratis en La Coctelera