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:
- Baseado em Promises: Diferente do modelo de callbacks do
XMLHttpRequest, ofetchutiliza Promises, o que resulta em um código mais limpo, legível e fácil de encadear. - Arquitetura Modular: A API é dividida em objetos específicos como
Request,ResponseeHeaders, tornando a manipulação de entradas e saídas mais organizada. - Manipulação via Streams: O
fetchlida 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
truepara 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.