Introdução à Fetch API
A Fetch API é a forma moderna e padronizada de fazer requisições HTTP no navegador, substituindo completamente o XMLHttpRequest. Ela oferece uma interface limpa baseada em Promises, tornando o consumo de APIs REST intuitivo e elegante. Quando você precisa buscar dados de um servidor, autenticar usuários ou enviar formulários sem recarregar a página, a Fetch API é sua ferramenta ideal.
Diferentemente de bibliotecas externas como Axios, a Fetch API é nativa do JavaScript moderno (disponível em todos os navegadores atuais). Isso significa zero dependências e melhor performance. Você escreve menos código, trata erros de forma consistente e integra-se perfeitamente com async/await.
Fundamentos e Sintaxe Básica
GET: Recuperando Dados
A forma mais simples de usar Fetch é fazer uma requisição GET para obter dados. A função fetch() retorna uma Promise que resolve para um objeto Response. Você deve chamar .json() para parsear o corpo da resposta como JSON.
// Requisição GET básica
fetch('https://jsonplaceholder.typicode.com/posts/1')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Erro:', error));
A versão com async/await é mais legível e se tornou o padrão na indústria:
async function obterPost() {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts/1');
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Erro na requisição:', error);
}
}
obterPost();
POST: Enviando Dados
Para criar novos recursos, use POST com um objeto de configuração contendo o método HTTP e os headers necessários:
async function criarPost() {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
title: 'Novo Post',
body: 'Conteúdo do post',
userId: 1
})
});
const data = await response.json();
console.log('Post criado:', data);
} catch (error) {
console.error('Erro ao criar post:', error);
}
}
Tratamento de Erros e Status HTTP
Verificando o Status da Resposta
Um erro crítico que iniciantes cometem é acreditar que fetch() rejeita a Promise em caso de erro HTTP. Na verdade, fetch() só rejeita em casos de falha de rede. Você deve verificar manualmente response.ok ou response.status:
async function buscarComValidacao() {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts/999');
if (!response.ok) {
throw new Error(`Erro HTTP: ${response.status}`);
}
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Erro capturado:', error.message);
}
}
AbortController: Cancelando Requisições
Em aplicações reais, você frequentemente precisa cancelar requisições (quando um usuário navega para outra página, por exemplo). Use AbortController:
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 5000);
fetch('https://jsonplaceholder.typicode.com/posts', {
signal: controller.signal
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => {
if (error.name === 'AbortError') {
console.log('Requisição cancelada');
}
})
.finally(() => clearTimeout(timeoutId));
Padrões Avançados e Boas Práticas
Função Helper Reutilizável
Crie uma função wrapper que centraliza configurações comuns, como headers de autenticação:
async function apiRequest(endpoint, options = {}) {
const defaultOptions = {
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${localStorage.getItem('token')}`
}
};
const config = { ...defaultOptions, ...options };
const response = await fetch(`https://api.exemplo.com${endpoint}`, config);
if (!response.ok) {
throw new Error(`API Error: ${response.status}`);
}
return response.json();
}
// Uso
apiRequest('/usuarios', { method: 'GET' })
.then(usuarios => console.log(usuarios))
.catch(error => console.error(error));
Tratando Diferentes Tipos de Resposta
Nem sempre a resposta é JSON. Use response.headers.get('content-type') para validar:
async function processarResposta() {
const response = await fetch('https://jsonplaceholder.typicode.com/posts/1');
const contentType = response.headers.get('content-type');
let data;
if (contentType.includes('application/json')) {
data = await response.json();
} else if (contentType.includes('text/plain')) {
data = await response.text();
} else {
data = await response.blob();
}
return data;
}
Upload de Arquivos com FormData
Para enviar arquivos, use FormData em vez de JSON:
async function enviarArquivo(arquivo) {
const formData = new FormData();
formData.append('arquivo', arquivo);
formData.append('descricao', 'Meu arquivo');
const response = await fetch('https://api.exemplo.com/upload', {
method: 'POST',
body: formData
// Note: não defina 'Content-Type', o navegador faz isso automaticamente
});
return response.json();
}
Conclusão
Você aprendeu que Fetch API é a forma moderna e nativa de consumir APIs REST, eliminando a necessidade de bibliotecas externas para operações básicas. Dominar async/await e a importância de validar response.ok são fundamentos críticos que diferenciam código profissional de código frágil. Por fim, padrões como funções helpers e AbortController transformam requisições simples em sistemas robusto, prontos para produção.