fetch()
te permite realizar solicitudes de red similares a XMLHttpRequest (XHR). La diferencia principal es que la API de Fetch usa promesas, que tienen una API más simple para ayudarte a evitar las devoluciones de llamada complicadas en la API de XMLHttpRequest.
Si nunca usaste promesas, consulta 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, además de una llamada a open()
y send()
.
Ejemplo de la documentación de MDN.
function reqListener() {
var data = JSON.parse(this.responseText);
console.log(data);
}
function reqError(err) {
console.log('Fetch Error :-S', err);
}
var 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(
function(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(function(err) {
console.log('Fetch Error :-S', err);
});
La solicitud fetch()
necesita solo una llamada para hacer el mismo trabajo que el ejemplo de XHR. Para procesar la respuesta, primero verificamos que su estado sea 200 y, luego, la analizamos 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 muestra una promesa.
La transmisión se realiza de forma asíncrona.
Metadatos de las respuestas
En el ejemplo anterior, se mostró el estado del objeto Response y cómo analizar la respuesta como JSON. Aquí te mostramos cómo controlar otros metadatos a los que podrías querer acceder, como los encabezados:
fetch('users.json').then(function(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
". Estas types
muestran de dónde proviene el recurso y puedes usarlas 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 en la respuesta.
Si se realiza una solicitud para un recurso en otro origen, y ese origen muestra 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 de opaque
provienen de un origen diferente que no muestra encabezados de CORS. Con una respuesta opaca, no podremos leer los datos mostrados ni ver el estado de la solicitud, lo que significa que no podrás verificar si la solicitud se realizó de forma correcta.
Puedes definir un modo para una solicitud de recuperación de forma que solo se resuelvan ciertos tipos de solicitudes. Los modos que puedes configurar son los siguientes:
same-origin
solo se realiza de forma correcta para las solicitudes de elementos del mismo origen y rechaza todas las demás solicitudes.cors
permite solicitudes de elementos en el mismo origen y en otros orígenes que muestran los encabezados de CORs adecuados.cors-with-forced-preflight
realiza una comprobación previa antes de realizar cualquier solicitud.no-cors
está diseñado para realizar solicitudes a otros orígenes que no tienen encabezados de CORS y dan como resultado una respuestaopaque
, pero como se indica , esto no es posible en el momento global de la ventana.
Para definir el modo, agrega un objeto de opciones como 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(function(response) {
return response.text();
})
.then(function(text) {
console.log('Request successful', text);
})
.catch(function(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 en todas las solicitudes de recuperación.
Si trabajas con una API de JSON, debes verificar el estado y analizar el JSON de cada respuesta. Para simplificar tu código, define el estado y el análisis de JSON en funciones separadas que muestren promesas y usa la solicitud de recuperación para manejar 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(function(data) {
console.log('Request succeeded with JSON response', data);
}).catch(function(error) {
console.log('Request failed', error);
});
En este ejemplo, se define una función status
que verifica el response.status
y muestra una promesa resuelta como Promise.resolve()
o una rechazada como Promise.reject()
.
Este es el primer método al que se llama en la cadena fetch()
.
Si se resuelve la promesa, la secuencia de comandos llama al método json()
, que muestra 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 sentencia 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 e incluir algunos parámetros en el cuerpo de la solicitud. Para ello, configura los parámetros method
y body
en las opciones fetch()
:
fetch(url, {
method: 'post',
headers: {
"Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
},
body: 'foo=bar&lorem=ipsum'
})
.then(json)
.then(function (data) {
console.log('Request succeeded with JSON response', data);
})
.catch(function (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, configura el valor credentials
de la solicitud en "include"
:
fetch(url, {
credentials: 'include'
})