XMLHttpRequest (XHR) fue inventado por Microsoft a principios de los años 90 y se convirtió en una tecnología de referencia para las interacciones asincrónicas del servidor a mediados de la primera década del siglo XXI.
Gracias a XHR, por primera vez fue posible actualizar partes de una página web sin recargar toda la página.
XMLHttpRequest
es un objeto de navegador integrado en todos los navegadores modernos que se puede utilizar para realizar solicitudes HTTP en JavaScript para intercambiar datos entre el navegador web y el servidor.
A pesar de la palabra "XML" en su nombre, XMLHttpRequest
se puede usar para recuperar cualquier tipo de datos y no solo XML. Podemos usarlo para cargar/descargar archivos, enviar datos de formularios, realizar un seguimiento del progreso y mucho más.
Solicitud básica de XHR
Para enviar una solicitud HTTP usando XHR, cree un XMLHttpRequest
objeto, abra una conexión a la URL y envíe la solicitud. Una vez que se complete la solicitud, el objeto contendrá información útil, como el cuerpo de la respuesta y el código de estado HTTP.
Usemos la API REST de prueba JSONPlaceholder para enviar una solicitud GET usando XHR:
// create an XHR object
const xhr = new XMLHttpRequest();
// listen for `onload` event
xhr.onload = () => {
// process response
if (xhr.status == 200) {
// parse JSON data
console.log(JSON.parse(xhr.response));
} else {
console.error('Error!');
}
};
// create a `GET` request
xhr.open('GET', 'https://jsonplaceholder.typicode.com/users');
// send request
xhr.send();
xhr.open()
Método
En el ejemplo anterior, pasamos el método HTTP y una URL a la solicitud al open()
método. Este método normalmente se llama justo después de new XMLHttpRequest()
. Podemos usar este método para especificar los parámetros principales de la solicitud:
Esta es la sintaxis de este método:
xhr.open(method, URL, [async, user, password])
method
— Método de solicitud HTTP. Puede serGET
,POST
,DELETE
,PUT
, etc.URL
— La URL a solicitar, una cadena o un objeto de URLasnyc
— Especificar si la solicitud debe hacerse de forma asíncrona o no. El valor predeterminado estrue
username
&password
— Credenciales para la autenticación HTTP básica
El open()
El método no abre la conexión a la URL. Solo configura la solicitud HTTP.
xhr.send()
Método
xhr.send([body])
El send()
El método abre la conexión de red y envía la solicitud al servidor. Se necesita un body
opcional parámetro que contiene el cuerpo de la solicitud. Para métodos de solicitud como GET
no necesita pasar el parámetro del cuerpo.
Eventos XHR
Los tres eventos XHR más utilizados son los siguientes:
load
— Este evento se llama cuando el resultado está listo. Es equivalente axhr.onreadystatechange
evento conxhr.readyState == 4
.error
— Este evento se activa cuando la solicitud falla debido a una caída de la red o una URL no válida.progress
— Este evento se activa periódicamente durante la descarga de la respuesta. Se puede usar para informar el progreso de solicitudes de red grandes.
// listen for `load` event
xhr.onload = () => {
console.log(`Data Loaded: ${xhr.status} ${xhr.response}`);
};
// listen for `error` event
xhr.onerror = () => {
console.error('Request failed.');
}
// listen for `progress` event
xhr.onprogress = (event) => {
// event.loaded returns how many bytes are downloaded
// event.total returns the total number of bytes
// event.total is only available if server sends `Content-Length` header
console.log(`Downloaded ${event.loaded} of ${event.total}`);
}
Tiempo de espera de solicitud
Puede configurar fácilmente el tiempo de espera de la solicitud especificando el tiempo en milisegundos:
// set timeout
xhr.timeout = 5000; // 5 seconds
// listen for `timeout` event
xhr.ontimeout = () => console.log('Request timeout.', xhr.responseURL);
Tipo de respuesta
Podemos usar xhr.responseType
propiedad para establecer el formato de respuesta esperado:
- Vacío (predeterminado) o
text
— texto sin formato json
— JSON analizadoblob
— Blob de datos binariosdocument
— Documento XMLarraybuffer
—ArrayBuffer
para datos binarios
Llamemos a una API RESTful para obtener la respuesta como JSON:
const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.jsonbin.io/b/5d5076e01ec3937ed4d05eab/1');
// set response format
xhr.responseType = 'json';
xhr.send();
xhr.onload = () => {
// get JSON response
const user = xhr.response;
// log details
console.log(user.name); // John Doe
console.log(user.email); // [email protected]
console.log(user.website); // http://example.com
}
Estados de solicitud (xhr.readyState
)
El XMLHttpRequest
el objeto cambia de estado a medida que avanza la solicitud. Podemos acceder al estado actual usando xhr.readyState
propiedad.
Los estados son:
UNSENT
(0) — El estado inicialOPENED
(1) — Comienza la solicitudHEADERS_RECEIVED
(2) — Los encabezados HTTP recibidosLOADING
(3) — La respuesta se está cargandoDONE
(4) — La solicitud está completa
Podemos rastrear el estado de la solicitud usando onreadystatechange
evento:
xhr.onreadystatechange = function () {
if(xhr.readyState == 1) {
console.log('Request started.');
}
if(xhr.readyState == 2) {
console.log('Headers received.');
}
if (xhr.readyState == 3) {
console.log('Data loading..!');
}
if (xhr.readyState == 4) {
console.log('Request ended.');
}
};
Solicitud de cancelación
Podemos cancelar fácilmente una solicitud XHR en cualquier momento llamando al abort()
método en el xhr
objeto:
xhr.abort(); // cancel request
Solicitudes sincrónicas
De forma predeterminada, XHR realiza una solicitud asincrónica que es buena para el rendimiento. Pero si desea realizar una solicitud síncrona explícita, simplemente pase false
como tercer argumento para open()
método. Pausará la ejecución de JavaScript en send()
y reanudar cuando la respuesta esté disponible:
xhr.open('GET', 'https://api.jsonbin.io/b/5d5076e01ec3937ed4d05eab/1', false);
Encabezados HTTP
XMLHttpRequest
nos permite establecer encabezados de solicitud, así como encabezados de respuesta de lectura. Podemos configurar la solicitud Content-Type
&Accept
encabezados llamando a setRequestHeader()
método en el xhr
objeto:
// set request headers
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('Accept', '*/*'); // accept all
Del mismo modo, si desea leer los encabezados de respuesta (excepto Set-Cookie
), llama al getResponseHeader()
en el xhr
objeto:
// read response headers
xhr.getResponseHeader('Content-Type');
xhr.getResponseHeader('Cache-Control');
¿Quiere obtener encabezados de respuesta a la vez? Utilice getAllResponseHeaders()
en cambio:
xhr.getAllResponseHeaders();
Solicitud POST XHR
El XMLHttpRequest
La solicitud POST para enviar los datos de un formulario se puede enviar de dos maneras:
- Usando solo Ajax
- Usando
FormData
API
El primer enfoque es lo suficientemente bueno a menos que desee cargar un archivo y necesite multipart/form-data
codificación Así es como podemos hacer una solicitud POST con datos de formulario codificados en URL:
const xhr = new XMLHttpRequest();
// configure a `POST` request
xhr.open('POST', '/login');
// prepare form data
let params = 'username=attacomsian&password=123456';
// set `Content-Type` header
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
// pass `params` to `send()` method
xhr.send(params);
// listen for `load` event
xhr.onload = () => {
console.log(xhr.responseText);
}
¿Quieres hacer una solicitud JSON POST? Asegúrese de convertir los datos JSON en una cadena usando JSON.stringify() y configure el Content-Type
encabezado a application/json
:
const xhr = new XMLHttpRequest();
// configure a `POST` request
xhr.open('POST', '/login');
// create a JSON object
const params = {
username: 'attacomsian',
password: '123456'
};
// set `Content-Type` header
xhr.setRequestHeader('Content-Type', 'application/json');
// pass `params` to `send()` method
xhr.send(JSON.stringify(params));
// listen for `load` event
xhr.onload = () => {
console.log(xhr.responseText);
}
Solicitudes y cookies de origen cruzado
XMLHttpRequest
puede enviar solicitudes de origen cruzado, pero está sujeto a medidas de seguridad especiales. Para solicitar un recurso de un servidor diferente, el servidor debe admitirlo explícitamente mediante CORS (intercambio de recursos de origen cruzado).
Al igual que Fetch API, XHR no envía cookies ni autorización HTTP a otro origen. Para enviar cookies, puede usar withCredentials
propiedad del xhr
objeto:
xhr.withCredentials = true;
XHR frente a jQuery
Métodos de contenedor de jQuery como $.ajax()
utiliza XHR bajo el capó y proporciona un mayor nivel de abstracción para facilitar la vida de los desarrolladores. Usando jQuery, podemos traducir el código anterior en unas pocas líneas:
$.ajax('https://jsonplaceholder.typicode.com/users')
.done(data => {
console.log(data);
}).fail(err => {
console.error('Error:', err);
});
XHR frente a la API de obtención
Fetch API es una alternativa moderna basada en promesas a XHR. Es limpio, más fácil de entender y se usa masivamente en los trabajadores de servicio de PWA.
El ejemplo anterior de XHR se puede convertir a un fetch()
mucho más simple -código basado que incluso analiza automáticamente el JSON devuelto:
fetch('https://jsonplaceholder.typicode.com/users')
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error('Error:', err));
¿Quieres saber más? Consulte la guía de JavaScript Fetch API para comprender cómo puede usar Fetch API para solicitar recursos de red con solo unas pocas líneas de código.