Entendendo a API Fetch no JavaScript Moderno

A API fetch é a interface moderna do JavaScript para realizar requisições HTTP, substituindo gradualmente o antigo XMLHttpRequest. Ela oferece uma maneira mais poderosa e flexível de interagir com recursos de rede.

Principais Diferenças em Relação ao XMLHttpRequest

Existem três pilares que tornam o fetch superior às tecnologias anteriores:

  1. Baseado em Promises: Diferente do modelo de callbacks do XMLHttpRequest, o fetch utiliza Promises, o que resulta em um código mais limpo, legível e fácil de encadear.
  2. Arquitetura Modular: A API é dividida em objetos específicos como Request, Response e Headers, tornando a manipulação de entradas e saídas mais organizada.
  3. Manipulação via Streams: O fetch lida com os dados através de fluxos (Streams). Isso permite processar partes de um arquivo antes mesmo que ele seja totalmente baixado, otimizando a memória e a performance em conexões lentas ou arquivos grandes.

Uso Fundamental e Sintaxe

Em sua forma mais simples, o fetch() aceita a URL do recurso e retorna uma Promise. Embora funcione com o método .then(), a abordagem com async/await é recomendada pela clareza semântica.

async function buscarUsuario() {
  const endpoint = 'https://jsonplaceholder.typicode.com/users/1';
  try {
    const resposta = await fetch(endpoint);
    const dados = await resposta.json();
    console.log(dados);
  } catch (erro) {
    console.error('Falha na comunicação:', erro);
  }
}

No exemplo acima, o await fetch() retorna um objeto de resposta. O método resposta.json() também é assíncrono, pois ele lê o stream de dados e o covnerte em um objeto JavaScript.

Trabalhando com o Objeto Response

Ao realizar uma requisição, recebemos um objeto Response. Ele contém informações síncronas que podem ser lidas imediatamente, como o status da conexão.

Propriedades de Verificação

  • Response.ok: Um booleano que retorna true para códigos de status entre 200 e 299.
  • Response.status: O código numérico HTTP (ex: 200, 404, 500).
  • Response.statusText: A mensagem textual correspondente ao status (ex: "OK" ou "Not Found").
  • Response.url: A URL final da requisição (útil para identiifcar redirecionamentos).

Tratamento de Erros

Um detalhe crucial: o fetch não lança um erro (reject) para códigos de erro HTTP como 404 ou 500. Ele só falha em caso de erros de rede ou se a requisição não puder ser completada. Para validar se a requisição foi bem-sucedida, deve-se checar a propriedade ok.

async function carregarDocumento(caminho) {
  const res = await fetch(caminho);
  
  if (!res.ok) {
    throw new Error(`Erro na requisição: ${res.status}`);
  }
  
  return await res.text();
}

Manipulando Cabeçalhos (Headers)

O atributo response.headers permite acessar os metadados da resposta. Você pode iterar sobre eles ou buscar valores específicos.

const r = await fetch('https://api.exemplo.com/dados');
console.log(r.headers.get('Content-Type'));

for (let [chave, valor] of r.headers) {
  console.log(`${chave}: ${valor}`);
}

Métodos para Extração de Dados

Dependendo do tipo de conteúdo retornado pelo servidor, existem diferentes formas de processar o corpo da resposta:

  • .json(): Para dados estruturados em JSON.
  • .text(): Para strings de texto puro ou HTML.
  • .blob(): Para arquivos binários como imagens e PDFs.
  • .arrayBuffer(): Para dados binários de baixo nível (áudio, vídeo).
  • .formData(): Para processar dados de formulários.

Aviso: O corpo da resposta é um stream e só pode ser lido uma vez. Se precisar ler os dados múltiplas vezes, utilize o método response.clone().

const original = await fetch('/imagem.png');
const copia = original.clone();

const blob1 = await original.blob();
const blob2 = await copia.blob(); // Funciona devido ao clone

Customizando a Requisição (Segundo Parâmetro)

Para enviar dados ou alterar o método HTTP, passamos um objeto de configuração como segundo argumento.

Enviando uma Requisição POST com JSON

async function criarPostagem(conteudo) {
  const configuracao = {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(conteudo)
  };

  const resposta = await fetch('https://jsonplaceholder.typicode.com/posts', configuracao);
  return await resposta.json();
}

const novoPost = { titulo: 'Fetch API', autor: 'Dev' };
criarPostagem(novoPost);

Upload de Arquivos com FormData

Ao lidar com formulários ou uploads, o FormData facilita o processo, definindo automaticamente os cabeçalhos apropriados.

const seletorArquivo = document.querySelector('input[type="file"]');
const formulario = new FormData();

formulario.append('avatar', seletorArquivo.files[0]);
formulario.append('usuario_id', '123');

fetch('/upload', {
  method: 'POST',
  body: formulario
});

Quando enviamos um FormData, o navegador define o Content-Type como multipart/form-data automaticamente, incluindo o delimitador (boundary) necessário.

Tags: javascript fetch-API HTTP promises web-development

Publicado em 6-27 08:06