fetch() te permite realizar solicitudes de red similares a XMLHttpRequest (XHR). La
diferencia principal es que la API de Fetch usa Promises, que tiene una
API más simple para ayudarte a evitar las devoluciones de llamada complicadas en la
API de XMLHttpRequest.
Si nunca usaste promesas, consulta la Introducción a las promesas de JavaScript.
Solicitud de recuperación básica
A continuación, se muestra un ejemplo implementado con un XMLHttpRequest y, luego, con fetch. Queremos solicitar una URL, obtener una respuesta y analizarla
como JSON.
XMLHttpRequest
Un XMLHttpRequest necesita dos objetos de escucha para controlar los casos de éxito y error, y una llamada a open() y send().
Ejemplo de la documentación de MDN.
function reqListener () {
const data = JSON.parse(this.responseText);
console.log(data);
}
function reqError (err) {
console.log('Fetch Error :-S', err);
}
const oReq = new XMLHttpRequest();
oReq.onload = reqListener;
oReq.onerror = reqError;
oReq.open('get', './api/some.json', true);
oReq.send();
Recuperar
Nuestra solicitud de recuperación se ve de la siguiente manera:
fetch('./api/some.json')
.then(response => {
if (response.status !== 200) {
console.log(`Looks like there was a problem. Status Code: ${response.status}`);
return;
}
// Examine the text in the response
response.json().then(function(data) {
console.log(data);
});
})
.catch(err => {
console.log('Fetch Error :-S', err);
});
La solicitud fetch() solo necesita una llamada para realizar el mismo trabajo que el ejemplo de XHR. Para procesar la respuesta, primero verificamos que el estado de la respuesta sea
200 y, luego, analizamos la respuesta como JSON. La respuesta a una solicitud fetch() es un objeto
Stream, lo que significa que, después de
llamar al método json(), se devuelve una promesa.
La transmisión se produce de forma asíncrona.
Metadatos de la respuesta
En el ejemplo anterior, se mostró el estado del objeto Response y cómo analizar la respuesta como JSON. A continuación, se muestra cómo controlar otros metadatos a los que quieras acceder, como los encabezados:
fetch('users.json').then(response => {
console.log(response.headers.get('Content-Type'));
console.log(response.headers.get('Date'));
console.log(response.status);
console.log(response.statusText);
console.log(response.type);
console.log(response.url);
});
Tipos de respuesta
Cuando realizamos una solicitud de recuperación, la respuesta recibirá un response.type
de "basic",
"cors" o
"opaque".
Estos types muestran de dónde proviene el recurso, y puedes usarlos para
determinar cómo tratar el objeto de respuesta.
Cuando el navegador solicita un recurso en el mismo origen, la respuesta tiene un tipo basic con restricciones sobre lo que puedes ver de la respuesta.
Si se realiza una solicitud de un recurso en otro origen y ese origen devuelve
encabezados de CORS, el tipo es cors. Las respuestas cors
son similares a las respuestas basic, pero restringen los encabezados que
puedes ver a Cache-Control, Content-Language, Content-Type, Expires,
Last-Modified y Pragma.
Las respuestas opaque provienen de un origen diferente que no devuelve encabezados
de CORS. Con una respuesta opaca, no podremos
leer los datos que se devuelven ni ver el estado de la solicitud, lo que significa que no podrás verificar
si la solicitud se realizó correctamente.
Puedes definir un modo para una solicitud de recuperación de modo que solo se resuelvan ciertos tipos de solicitudes. Los modos que puedes configurar son los siguientes:
same-originsolo se ejecuta correctamente para las solicitudes de recursos en el mismo origen y rechaza todas las demás solicitudes.corspermite solicitudes de recursos en el mismo origen y en otros que devuelven los encabezados de CORS adecuados.cors-with-forced-preflightrealiza una verificación preliminar antes de realizar cualquier solicitud.no-corsestá diseñado para realizar solicitudes a otros orígenes que no tienen encabezados de CORS y que dan como resultado una respuestaopaque, pero, como se indicó, esto no es posible en el alcance global de la ventana en este momento.
Para definir el modo, agrega un objeto de opciones como el segundo parámetro en la
solicitud fetch y define el modo en ese objeto:
fetch('http://some-site.com/cors-enabled/some.json', {mode: 'cors'})
.then(response => response.text())
.then(text => {
console.log('Request successful', text);
})
.catch(error => {
log('Request failed', error)
});
Encadenamiento de promesas
Una de las grandes características de las promesas es la capacidad de encadenarlas. En el caso de fetch(), esto te permite compartir la lógica entre las solicitudes de recuperación.
Si trabajas con una API de JSON, debes verificar el estado y analizar el JSON para cada respuesta. Puedes simplificar tu código definiendo el estado y el análisis de JSON en funciones separadas que devuelvan promesas, y usar la solicitud fetch para controlar solo los datos finales y el caso de error.
function status (response) {
if (response.status >= 200 && response.status < 300) {
return Promise.resolve(response)
} else {
return Promise.reject(new Error(response.statusText))
}
}
function json (response) {
return response.json()
}
fetch('users.json')
.then(status)
.then(json)
.then(data => {
console.log('Request succeeded with JSON response', data);
}).catch(error => {
console.log('Request failed', error);
});
En este ejemplo, se define una función status que verifica el response.status y
devuelve una promesa resuelta como
Promise.resolve()
o una promesa rechazada como
Promise.reject().
Este es el primer método al que se llama en la cadena fetch().
Si la promesa se resuelve, la secuencia de comandos llama al método json(), que
devuelve una segunda promesa de la llamada a response.json() y crea un
objeto que contiene el JSON analizado. Si el análisis falla, se rechaza la promesa
y se ejecuta la instrucción catch.
Esta estructura te permite compartir la lógica en todas tus solicitudes de recuperación, lo que facilita el mantenimiento, la lectura y la prueba del código.
solicitud POST
A veces, una app web necesita llamar a una API con un método POST y, además, incluir algunos
parámetros en el cuerpo de la solicitud. Para ello, configura los parámetros method y body
en las opciones de fetch():
fetch(url, {
method: 'post',
headers: {
"Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
},
body: 'foo=bar&lorem=ipsum'
})
.then(json)
.then(data => {
console.log('Request succeeded with JSON response', data);
})
.catch(error => {
console.log('Request failed', error);
});
Envía credenciales con una solicitud de recuperación
Para realizar una solicitud de recuperación con credenciales, como cookies, establece el valor credentials de la solicitud en "include":
fetch(url, {
credentials: 'include'
})