Cómo utilizar la API Fetch para realizar solicitudes HTTP en JavaScript

Fetch API es una API de JavaScript basada en promesas para realizar solicitudes HTTP asíncronas en el navegador de forma similar a XMLHttpRequest (XHR). A diferencia de XHR, es una API simple y limpia que utiliza promesas para proporcionar un conjunto de funciones más potente y flexible para obtener recursos del servidor.

Fetch API está bastante estandarizado ahora y es compatible con todos los navegadores modernos, excepto IE. Si necesita admitir todos los navegadores, incluido IE, solo agregue un polyfill lanzado por GitHub a su proyecto.

Uso básico de la API

Usar Fetch API es realmente simple. Simplemente pase la URL, la ruta al recurso que desea obtener, a fetch() método:

fetch('/js/users.json')
    .then(response => {
        // handle response data
    })
    .catch(err => {
        // handle errors
    });

Pasamos la ruta del recurso que queremos recuperar como parámetro a fetch() . Devuelve una promesa que pasa la respuesta a then() cuando se cumple. El catch() El método intercepta errores si la solicitud no se completa debido a una falla en la red o por cualquier otra razón.

Solicitud OBTENER

De manera predeterminada, Fetch API usa el método GET para solicitudes asíncronas. Usemos la API REST de Reqres para recuperar una lista de usuarios que usan la solicitud GET:

fetch('https://reqres.in/api/users')
    .then(res => res.json())
    .then(res => {
        res.data.map(user => {
            console.log(`${user.id}: ${user.first_name} ${user.last_name}`);
        });
    });

La solicitud anterior imprime lo siguiente en la consola:

1: George Bluth
2: Janet Weaver
3: Emma Wong

Llamando a fetch() método devuelve una promesa. La respuesta devuelta por la promesa es un objeto de flujo, lo que significa que cuando llamamos a json() método, devuelve otra promesa. Llamar al json() El método indica que estamos esperando una respuesta JSON. Si espera una respuesta XML, debe usar text() método.

Solicitud POST

Al igual que Axios, Fetch también nos permite usar cualquier otro método HTTP en la solicitud:POST, PUT, DELETE, HEAD y OPTIONS. Todo lo que necesita hacer es establecer el method y body parámetros en el fetch() opciones:

const user = {
    first_name: 'John',
    last_name: 'Lilly',
    job_title: 'Software Engineer'
};

const options = {
    method: 'POST',
    body: JSON.stringify(user),
    headers: {
        'Content-Type': 'application/json'
    }
}

fetch('https://reqres.in/api/users', options)
    .then(res => res.json())
    .then(res => console.log(res));

La API de Reqres nos devuelve los datos del cuerpo con un ID y una marca de tiempo creada adjunta:

{  
   "first_name":"John",
   "last_name":"Lilly",
   "job_title":"Software Engineer",
   "id":"482",
   "createdAt":"2019-05-12T15:09:13.140Z"
}

Solicitud de ELIMINACIÓN

La solicitud DELETE se parece mucho a la solicitud POST excepto body no es obligatorio:

const options = {
    method: 'DELETE',
    headers: {
        'Content-Type': 'application/json'
    }
}

fetch('https://reqres.in/api/users/2', options)
    .then(res => {
        if (res.ok) {
            return Promise.resolve('User deleted.');
        } else {
            return Promise.reject('An error occurred.');
        }
    })
    .then(res => console.log(res));

Gestión de errores

Desde el fetch() método devuelve una promesa, el manejo de errores es fácil. Podemos usar el catch() método de la promesa de interceptar cualquier error que se produzca durante la ejecución de la solicitud. Sin embargo, no se generará ningún error si la solicitud llega al servidor y regresa, independientemente de la respuesta que haya devuelto el servidor. La promesa devuelta por el fetch() no rechaza los errores HTTP incluso si el código de respuesta HTTP es 404 o 500.

Afortunadamente, puedes usar el ok propiedad del objeto de respuesta para verificar si la solicitud fue exitosa o no:

fetch('https://reqres.in/api/users/22') // 404 Error
    .then(res => {
        if (res.ok) {
            return res.json();
        } else {
            return Promise.reject(res.status);
        }
    })
    .then(res => console.log(res))
    .catch(err => console.log(`Error with message: ${err}`));

Encabezados de solicitud

Encabezados de solicitud (como Accept , Content-Type , User-Agent , Referer , etc.) son una parte esencial de cualquier solicitud HTTP. Headers de la API Fetch El objeto nos permite establecer, eliminar o recuperar encabezados de solicitud HTTP.

Podemos crear un objeto de encabezado usando el Headers() constructor y luego use el append , has , get , set y delete métodos para modificar encabezados de solicitud:

// create an empty `Headers` object 
const headers = new Headers();

// add headers
headers.append('Content-Type', 'text/plain');
headers.append('Accept', 'application/json');

// add custom headers
headers.append('X-AT-Platform', 'Desktop');
headers.append('X-AT-Source', 'Google Search');

// check if header exists
headers.has('Accept'); // true

// get headers
headers.get('Accept'); // application/json
headers.get('X-AT-Source'); // Google Search

// update header value
headers.set('Content-Type', 'application/json');

// remove headers
headers.delete('Content-Type');
headers.delete('X-AT-Platform');

También podemos pasar una matriz de matrices o un objeto literal al constructor para crear un objeto de encabezado:

// passing an object literal
const headers = new Headers({
    'Content-Type': 'application/json',
    'Accept': 'application/json'
});

// OR

// passing an array of arrays
const headers = new Headers([
    ['Content-Type', 'application/json'],
    ['Accept', 'application/json']
]);

Para agregar encabezados a la solicitud, simplemente cree un Request instancia, y pásela a fetch() método en lugar de la URL:

const request = new Request('https://reqres.in/api/users', {
    headers: headers
});

fetch(request)
    .then(res => res.json())
    .then(json => console.log(json))
    .catch(err => console.error('Error:', err));

Objeto de solicitud

El Request El objeto representa una solicitud de recursos y se puede crear llamando al Request() constructor:

const request = new Request('https://reqres.in/api/users');

El Request object también acepta un objeto URL:

const url = new URL('https://reqres.in/api/users');
const request = new Request(url);

Pasando un Request objetar a fetch() , puede personalizar fácilmente las propiedades de la solicitud:

  • method — Método HTTP como GET , POST , PUT , DELETE , HEAD
  • url — La URL de la solicitud, una cadena o un objeto de URL
  • headers — un Headers objeto para encabezados de solicitud
  • referrer — remitente de la solicitud (p. ej., client )
  • mode — El modo para solicitudes de origen cruzado (p. ej., cors , no-cors , same-origin )
  • credentials — ¿Deberían acompañar la solicitud las cookies y los encabezados de autorización HTTP? (por ejemplo, include , omit , same-origin )
  • redirect — El modo de redirección de la solicitud (por ejemplo, follow , error , manual )
  • integrity — El valor de integridad del subrecurso de la solicitud
  • cache — El modo de caché de la solicitud (por ejemplo, default , reload , no-cache )

Vamos a crear un Request objeto con algunas propiedades personalizadas y contenido del cuerpo para realizar una solicitud POST:

const user = {
    first_name: 'John',
    last_name: 'Lilly',
    job_title: 'Software Engineer'
};

const headers = new Headers({
    'Content-Type': 'application/json',
    'Accept': 'application/json'
});

const request = new Request('https://reqres.in/api/users', {
    method: 'POST',
    headers: headers,
    redirect: 'follow',
    mode: 'cors',
    body: JSON.stringify(user)
});

fetch(request)
    .then(res => res.json())
    .then(json => console.log(json))
    .catch(err => console.error('Error:', err));

Solo se requiere el primer argumento, la URL. Todas estas propiedades son de solo lectura, lo que significa que no puede cambiar su valor una vez que se crea el objeto de solicitud. La API Fetch no requiere estrictamente un Request objeto. El objeto literal, lo pasamos a fetch() método, actúa como un Request objeto:

fetch('https://reqres.in/api/users', {
    method: 'POST',
    headers: headers,
    redirect: 'follow',
    mode: 'cors',
    body: JSON.stringify(user)
}).then(res => res.json())
    .then(json => console.log(json))
    .catch(err => console.error('Error:', err));

Objeto de respuesta

El Response objeto devuelto por el fetch() contiene la información sobre la solicitud y la respuesta de la solicitud de red, incluidos los encabezados, el código de estado y el mensaje de estado:

fetch('https://reqres.in/api/users')
    .then(res => {
        // get response headers
        console.log(res.headers.get('content-type'));
        console.log(res.headers.get('expires'));

        // HTTP response status code 
        console.log(res.status);

        // shorthand for `status` between 200 and 299 
        console.log(res.ok); 

        // status message of the response e.g. `OK`
        console.log(res.statusText);

        // check if there was a redirect
        console.log(res.redirected);

        // get the response type (e.g., `basic`, `cors`)
        console.log(res.type);

        // the full path of the resource
        console.log(res.url);
    });

Se puede acceder al cuerpo de la respuesta a través de los siguientes métodos:

  • json() devuelve el cuerpo como un objeto JSON
  • text() devuelve el cuerpo como una cadena
  • blob() devuelve el cuerpo como un objeto Blob
  • formData() devuelve el cuerpo como un objeto FormData
  • arrayBuffer() devuelve el cuerpo como un objeto ArrayBuffer

Todos estos métodos devuelven una promesa. Aquí hay un ejemplo de text() método:

fetch('https://reqres.in/api/unknown/2')
    .then(res => res.text())
    .then(res => console.log(res));

El resultado de la llamada de red anterior será una cadena JSON:

'{"data":{"id":2,"name":"fuchsia rose","year":2001,"color":"#C74375","pantone_value":"17-2031"}}'

Obtener y cookies

De forma predeterminada, cuando utiliza Fetch para obtener un recurso, la solicitud no contiene credenciales como cookies. Si desea enviar cookies, debe habilitar explícitamente las credenciales como se muestra a continuación:

fetch(url, {
  credentials: 'include'
})

Obtener y Asíncrono/Esperar

Dado que Fetch es una API basada en promesas, podemos ir un paso más allá y usar la última sintaxis async/await de ES2017 para hacer que nuestro código sea aún más simple y sincrónico:

const fetchUsers = async () => {
    try {
        const res = await fetch('https://reqres.in/api/users');
        if (!res.ok) {
            throw new Error(res.status);
        }
        const data = await res.json();
        console.log(data);
    } catch (error) {
        console.log(error);
    }
}

fetchUsers();

Conclusión

Eso es todo para la introducción a JavaScript Fetch API. Es una gran mejora con respecto a XMLHttpRequest con una interfaz simple, elegante y fácil de usar. Fetch funciona muy bien para obtener recursos de red (incluso a través de la red dentro de los trabajadores del servicio). La API Fetch es compatible con todos los navegadores modernos, por lo que no hay necesidad de usar ningún relleno a menos que desee admitir IE.