Desarrollar fácilmente en entorno cliente/servidor

AJAX

1. Solicitud simple

AJAX (Asynchronous JavaScript and XML) sirve para realizar una solicitud a un servidor sin tener que recargar la página HTML actual. Junto con la posibilidad de modificarla dinámicamente, esto transforma una página HTML en una auténtica aplicación.

La solicitud puede ser síncrona (o bloqueante) o asíncrona (la forma más habitual). 

Para realizar una solicitud AJAX, se necesita un objeto de la clase XMLHttpRequest.

Por motivos de seguridad, la primera versión de XMLHttpRequest solo permite el acceso al servidor de origen de la página. Dado que esto resulta a veces poco práctico (por la obligación de redirigir a otros servidores), una segunda versión permite el uso de dominios diferentes, si bien requiere autorizaciones (CORS, por Cross-Origin Resource Sharing).

Para poder interceptar la respuesta, tiene a su disposición la propiedad onreadystatechange. El objetivo de esta propiedad es invocar la función de usuario proporcionada cuando se devuelve una parte o la totalidad de la respuesta del servidor. Una propiedad adicional, readyState, sirve para conocer el estado de avance de la recepción de la respuesta. La propiedad status sirve para conocer el código de respuesta del servidor HTTP, útil en caso de error (5XX, por ejemplo, para un error interno).

Cuando el objeto de solicitud está listo, solo queda ejecutarla mediante el método open con los argumentos del tipo de solicitud HTTP (GET o POST), la URL y un valor booleano para indicar si la solicitud es bloqueante (síncrona) o no (lo más habitual). Por último, para el envío final, utilizará el método send con los posibles parámetros como argumentos. Como se trata de una solicitud HTTP, la codificación de los parámetros es, por defecto, idéntica a la que se utiliza en una URL, es decir, con el formato clave=valor separados por &. Si los valores pueden contener caracteres reservados como &, entonces hay que realizar una codificación con la función encodeURIComponent.

Para este primer ejemplo, hemos creado un archivo ajax.txt que contiene el texto «Mis datos Ajax»; la codificación de este archivo es UTF-8. También hemos creado un archivo ajax.html que contiene el siguiente código:

<!DOCTYPE html>  ...

Carga dinámica de scripts

1. Primera implementación

Como hemos visto hasta ahora, la etiqueta script sirve para cargar un script JavaScript externo. Esta capacidad puede aprovecharse para emular una solicitud a un servidor sin estar limitada por el tipo de acceso, a diferencia de AJAX, que por defecto se limita a un dominio. Por lo tanto, en este caso el servidor no generará un formato JSON como respuesta, sino código JavaScript.

Para que la solicitud funcione, hay que crear dinámicamente la petición de carga. Para ello, buscamos en la página la etiqueta head y, a continuación, creamos una nueva etiqueta script antes de añadirla a la etiqueta de encabezado. Gracias al atributo onload, se nos notificará que la carga del script se ha completado (y, por lo tanto, que también se ha recibido la respuesta del servidor). Este es el tipo de funcionamiento que se da con la carga de módulos AMD (Asynchronous Module Definition). Cabe señalar que nada impide insertar también la etiqueta script en el cuerpo de la etiqueta body.

Dado que solicitamos un script mediante una URL, estamos limitados a solicitudes de tipo GET.

Para la prueba, hemos creado un archivo que emula la respuesta de un servidor: script1.js

const autor =   
{ apellido: "Brines", nombre: "Alejandro"  
};  
 
autor.libros = [  
    { titulo: "Ruby",  
    subtitulo: "Los fundamentos"  
    }  
];  

Para que la diferencia con el formato JSON sea bien visible...

Promesas

1. Principio

JavaScript ha introducido una forma estandarizada para gestionar todos los procesos asíncronos (como una solicitud AJAX). Estos procesos deben evitar el bloqueo del código y, para ello, el estándar ha introducido un sistema de suscripción denominado Promesa. Una promesa es una forma de contrato que establece que, si se produce un evento determinado, se ejecutará dicho proceso.

Esto se traduce en una clase Promise. Esta clase tiene un constructor que toma una función como argumento. Dicha función tiene dos argumentos: una función de procesamiento del usuario y una función para gestionar el error. En resumen, la clase Promise invoca esta función —que normalmente es asíncrona— y, a continuación, utiliza los argumentos para notificar si la operación se ha realizado con éxito o no.

En este ejemplo, simulamos un acceso asíncrono con un temporizador:

    const promesa = new Promise(  
        ( miProcesamiento,  
          miError   
        ) => {  
            setTimeout(   
                () => miProcesamiento(),  
                5000 );  
        }  
    );  
   
    promesa.then(   
        () => {  
            alert( "¡El procesamiento asíncrono ha finalizado!" )  
        }  
    );  

Tenemos un objeto promesa, que pasa al constructor de la clase Promise una función anónima (en este caso, una función flecha). En esta función, tenemos el argumento miProcesamiento, que es una nueva función. A continuación, el procesamiento asíncrono la invoca mediante la función setTimeout tras 5 segundos.

El usuario del objeto promesa necesita saber que la operación asíncrona ha finalizado...