A Fetch API consolidou-se como o padrão moderno para realizar requisições HTTP em JavaScript, superando o legado do XMLHttpRequest (XHR). Presente nativamente em todos os navegadores contemporâneos e no Node.js a partir da versão 18, ela oferece uma interface baseada em Promises, resultando em um código mais limpo e intuitivo. Para muitos cenários de comunicação com APIs, a Fetch API pode eliminar a necessidade de bibliotecas externas como jQuery.ajax() ou Axios, simplificando o desenvolvimento e reduzindo a pegada de dependências.
Requisição GET Fundamental
// GET Simples
const response = await fetch('https://api.example.com/users');
const users = await response.json();
console.log(users);
// Com tratamento de erro
async function getUsers() {
const response = await fetch('https://api.example.com/users');
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return response.json();
}
Atenção: É crucial entender que a função fetch() rejeita a Promise apenas em caso de falhas de rede (como servidor inacessível ou problemas de DNS). Erros HTTP, como 404 (Não Encontrado) ou 500 (Erro Interno do Servidor), são interpretados como respostas bem-sucedidas do servidor e não causam uma rejeição automática. Para validar o status da requisição, você deve verificar a propriedade response.ok manualmente.
Operações CRUD: POST, PUT e DELETE
const response = await fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer eyJhbGci...',
},
body: JSON.stringify({
name: 'Alice',
email: '[email protected]',
}),
});
const newUser = await response.json();
await fetch('https://api.example.com/users/123', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'Alice Atualizada' }),
});
await fetch('https://api.example.com/users/123', {
method: 'DELETE',
headers: { 'Authorization': 'Bearer token123' },
});
Manipulando Diferentes Tipos de Resposta
const response = await fetch(url);
// JSON
const data = await response.json();
// Texto puro
const text = await response.text();
// Dados binários (imagens, arquivos)
const blob = await response.blob();
// ArrayBuffer (binário bruto)
const buffer = await response.arrayBuffer();
// Dados de formulário
const formData = await response.formData();
// Metadados da resposta
console.log(response.status); // 200
console.log(response.statusText); // "OK"
console.log(response.ok); // true (200-299)
console.log(response.headers.get('Content-Type'));
AbortController: Cancelando Requisições em Andamento
const controller = new AbortController();
// Cancelar após 5 segundos
const timeoutId = setTimeout(() => controller.abort(), 5000);
try {
const response = await fetch('https://api.example.com/data', {
signal: controller.signal,
});
clearTimeout(timeoutId);
const data = await response.json();
} catch (err) {
if (err.name === 'AbortError') {
console.log('Requisição excedeu o tempo limite ou foi abortada.');
} else {
throw err;
}
}
Envio de Arquivos com Fetch
const formData = new FormData();
formData.append('avatar', fileInput.files[0]);
formData.append('name', 'Alice');
// Não defina Content-Type — o navegador o faz com o boundary
const response = await fetch('/api/upload', {
method: 'POST',
body: formData,
});
Criando um Cliente Fetch Reutilizável
class ApiClient {
constructor(baseUrl, token) {
this.baseUrl = baseUrl;
this.token = token;
}
async request(path, options = {}) {
const response = await fetch(`${this.baseUrl}${path}`, {
...options,
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.token}`,
...options.headers,
},
});
if (!response.ok) {
const error = await response.json().catch(() => ({}));
throw new Error(error.message || `HTTP ${response.status}`);
}
return response.json();
}
get(path) { return this.request(path); }
post(path, data) { return this.request(path, { method: 'POST', body: JSON.stringify(data) }); }
put(path, data) { return this.request(path, { method: 'PUT', body: JSON.stringify(data) }); }
delete(path) { return this.request(path, { method: 'DELETE' }); }
}
// Uso
const api = new ApiClient('https://api.example.com', 'token123');
const users = await api.get('/users');
const newUser = await api.post('/users', { name: 'Alice' });
Erros Comuns e Como Evitá-los na Fetch API
- Não verificar
response.ok: Como mencionado, falhas de rede causam rejeição, mas erros HTTP como 404 ou 500 não. Sempre valideresponse.okpara garantir que a requisição foi bem-sucedida no nível da aplicação. - Definir
Content-TypeparaFormData: Ao enviar dados comFormData, o navegador se encarrega de configurar o cabeçalhoContent-Type, incluindo o parâmetro `boundary` necessário. Definir este cabeçalho manualmente pode corromper sua requisição. - Chamar
response.json()(ou.text(),.blob(), etc.) múltiplas vezes: O corpo da resposta de uma requisição Fetch pode ser consumido apenas uma vez. Se precisar acessar os dados mais de uma vez, armazene o resultado em uma variável após a primeira chamada. - Não tratar o
AbortError: Ao utilizar oAbortControllerpara cancelar requisições, a Promise é rejeitada com um erro cujonameé `'AbortError'`. É essencial capturar e tratar este tipo específico de erro para evitar interrupções inesperadas ou lógica incorreta.
Experimente Nossas Ferramentas Gratuitas para Desenvolvedores
Otimize suas respostas de API e codifique parâmetros de requisição com facilidade.