Tutorial da API JavaScript Fetch: GET, POST, tratamento de erros e tempos limite
Fetch é a maneira integrada de chamar APIs de JavaScript, mas tem uma surpresa que surpreende quase todo mundo. Aprenda a enviar solicitações, lidar com todo tipo de falha e criar um pequeno ajudante que você possa reutilizar.
fetch()retorna uma promessa paraResponsee a leitura do corpo leva um segundoawait.- Erros HTTP como 404 e 500 não rejeitam, portanto sempre verifique
response.ok. - Para enviar JSON, use
JSON.stringifye defina o cabeçalhoContent-Type. - Fetch não tem opção de tempo limite padrão, então use
AbortSignal.timeout().
A maioria dos aplicativos da web modernos conversam com um servidor o tempo todo. A JavaScript Fetch API é a maneira padrão de fazer isso e está integrada aos navegadores e ao Node.js 18 e posterior, portanto, não há nada para instalar.
O uso básico leva duas linhas, mas muitos tutoriais param por aí e deixam de fora a parte que causa bugs reais: o tratamento de falhas. Testamos os exemplos neste guia em um pequeno servidor local no Node.js 24, e a saída mostrada vem dessa execução. example.com no código representa sua própria API. Se as promessas são novas para você, comece com Promessas JavaScript explicadas.
O que é a API de busca?
Fetch é uma interface baseada em promessas para fazer solicitações HTTP. Ele substituiu o antigo, baseado em retorno de chamada XMLHttpRequest, e muitos projetos agora o utilizam em vez de adicionar uma biblioteca para chamadas simples.
| Recurso | Buscar | Axios (biblioteca) |
|---|---|---|
| Instalação | Construído em | Adicionado como uma dependência |
| Corpo JSON | Stringifique você mesmo | Automático |
| Analisar resposta JSON | Ligue response.json() |
Automático |
| Erros HTTP rejeitados? | Não | Sim, por padrão |
| Tempo limite | Através de AbortSignal |
Uma opção timeout |
Uma solicitação GET
Fetch faz uma solicitação GET por padrão. Existem duas etapas, e cada uma precisa de await: primeiro chegam os cabeçalhos de resposta e depois você lê o corpo.
const response = await fetch("https://example.com/users/1");
const user = await response.json();
console.log(user);
// { id: 1, name: 'Asha' }
As duas etapas existem porque o corpo pode ser grande e chegar depois dos cabeçalhos. Em um script de navegador, o nível superior await precisa de um módulo, então você normalmente colocará isso dentro de uma função async. Consulte nosso guia JavaScript assíncrono/aguardado.
O objeto Resposta
Antes de ler o corpo, você pode inspecionar a resposta:
console.log(response.status, response.ok, response.headers.get("content-type"));
// 200 true application/json
| Propriedade ou método | Dá a você |
|---|---|
response.ok |
true para status 200 a 299 |
response.status |
O código de status, como 404 |
response.headers.get(name) |
Um cabeçalho de resposta |
response.json() |
O corpo analisado como JSON |
response.text() |
O corpo como uma corda |
response.blob() |
Dados binários, como uma imagem |
Um corpo pode ser lido apenas uma vez. Chamar json() uma segunda vez falhou em nosso teste:
await res.json();
await res.json();
// TypeError: Body is unusable: Body has already been read
Se você precisar lê-lo duas vezes, ligue para response.clone() primeiro.
A grande surpresa: um 404 não joga
Esta é a coisa mais importante neste artigo. Solicitamos um usuário que não existe:
const res = await fetch("https://example.com/users/999");
console.log(res.status, res.ok);
// 404 false
Nenhuma exceção foi lançada. No que diz respeito à busca, a solicitação funcionou: o servidor foi alcançado e respondeu. A promessa é rejeitada apenas quando nenhuma resposta utilizável chega, como acontece com uma falha de rede. Portanto, um código como este tem um bug oculto:
try {
const res = await fetch(url);
const data = await res.json(); // may be an error payload
showUser(data); // runs anyway for 404 and 500
} catch (error) {
showError(); // does not run for 404 or 500
}
Verifique nossa folha de referências de códigos de status HTTP para ver o que cada código significa.
Um ajudante reutilizável
Não repita essa verificação em todos os lugares. Embrulhe uma vez:
async function getJson(url, options) {
const response = await fetch(url, options);
if (!response.ok) {
throw new Error(`Request failed with status ${response.status}`);
}
return response.json();
}
try {
await getJson("https://example.com/users/999");
} catch (error) {
console.log("caught:", error.message);
}
// caught: Request failed with status 404
Agora, erros de HTTP e erros de rede terminam no mesmo catch. Vale a pena ter esta pequena função em todos os projetos. Uma versão real também pode ler uma mensagem de erro do corpo da resposta e manipular uma resposta 204 No Content, que não possui JSON para analisar.
POSTAR dados JSON
Passe um objeto de opções como segundo argumento. Para JSON, você deve fazer duas coisas: converter os dados em uma string e definir o cabeçalho.
const created = await getJson("https://example.com/users", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name: "Ben" }),
});
console.log(created);
// { id: 2, name: 'Ben', type: 'application/json' }
Nosso servidor de teste repetiu o tipo de conteúdo recebido, confirmando a chegada do cabeçalho. Esquecer esse cabeçalho é uma causa comum de erros confusos no servidor, porque muitos frameworks apenas analisam JSON quando ele é declarado. Para fazer upload de um formulário ou arquivos, passe um objeto FormData como corpo e não defina Content-Type, pois o próprio navegador precisa adicionar um valor de limite.
Outros métodos e opções
| Opção | Exemplo | Objetivo |
|---|---|---|
método |
"PUT", "PATCH", "DELETE" |
O método HTTP |
cabeçalhos |
{Autorização: "Portador..." } |
Solicitar cabeçalhos |
corpo |
JSON.stringify(data) |
O corpo da solicitação |
sinal |
AbortSignal.timeout(5000) |
Cancelando |
credenciais |
"incluir" |
Envio de cookies de origem cruzada |
esconderijo |
"sem loja" |
Comportamento do cache do navegador |
Escolhendo entre REST e outros estilos de API? Nossa comparação de REST vs GraphQL mostra como a busca se encaixa em cada um.
Cadeias de caracteres de consulta
Não crie strings de consulta juntando texto, pois caracteres especiais irão quebrá-las. URLSearchParams cuida da codificação para você:
const params = new URLSearchParams({ q: "red shoes", page: 2 });
console.log(params.toString());
// q=red+shoes&page=2
await getJson(`https://example.com/search?${params}`);
// { q: 'red shoes', page: '2' }
O servidor recebeu red shoes corretamente, com o espaço restaurado.
Tempo limite e cancelamento
O Fetch esperará muito tempo em um servidor lento, a menos que você informe o contrário. AbortSignal.timeout() define um limite. Nosso endpoint de teste levou dois segundos, contra um limite de 200 milissegundos:
try {
await fetch("https://example.com/slow", { signal: AbortSignal.timeout(200) });
} catch (error) {
console.log(error.name);
}
// TimeoutError
Para cancelar manualmente, por exemplo, quando um usuário sai de uma página ou digita um novo termo de pesquisa, use um AbortController:
const controller = new AbortController();
const pending = fetch("https://example.com/slow", { signal: controller.signal });
controller.abort();
try {
await pending;
} catch (error) {
console.log(error.name);
}
// AbortError
Para executar várias solicitações de uma vez, use Promise.all, que é muito mais rápido do que aguardá-las uma de cada vez:
const [user, search] = await Promise.all([
getJson("https://example.com/users/1"),
getJson("https://example.com/search?q=a&page=1"),
]);
Todo tipo de fracasso
Aqui está a aparência de cada falha em nossa execução, além de como diferenciá-las:
| Situação | O que acontece | Como detectá-lo |
|---|---|---|
| Servidor retorna 404 ou 500 | Promessa cumpre | response.ok é falso |
| O servidor não pode ser alcançado | Rejeita com TypeError |
pegar |
| Tempo limite atingido | Rejeita com TimeoutError |
error.name |
| Cancelado manualmente | Rejeita com AbortError |
error.name |
| O corpo não é JSON válido | json() rejeita com SyntaxError |
pegar |
Essa última linha é comum na produção. Um proxy que retorna um 502 geralmente envia uma página de erro HTML. Reproduzimos isso e res.json() lançou um SyntaxError. Marcar response.ok antes de analisar significa que você relata o problema real em vez de um erro de análise confuso.
Dica: teste esses caminhos de falha propositalmente. As ferramentas de desenvolvedor do navegador podem simular estar offline e as ferramentas de teste podem simular uma resposta 500. Nosso guia de teste de API com Postman abrange a verificação do lado da API.
CORS e credenciais
Em um navegador, uma solicitação de uma origem para outra está sujeita ao CORS, as regras de compartilhamento de recursos entre origens. Se você vir um erro mencionando Access-Control-Allow-Origin, a correção pertence ao servidor, que deve permitir o seu site. No seu JavaScript, a falha aparece apenas como um genérico TypeError, então procure no console do navegador o motivo real. O Node.js não impõe CORS, portanto, uma solicitação que funciona em um script ainda pode falhar no navegador.
Por padrão, os navegadores não enviam cookies em solicitações de origem cruzada. Defina credentials: "include" se precisar deles e certifique-se de que o servidor permita. Nunca coloque chaves de API secretas no JavaScript do navegador, pois qualquer pessoa pode lê-las. Mantenha-os em seu servidor.
Erros comuns
- Não verificando
response.ok. As respostas de erro são tratadas como sucesso. - Esquecer o segundo
await.response.json()também retorna uma promessa. - Esquecer
JSON.stringify. Passar um objeto conforme o corpo envia[object Object]. - Definir
Content-TypecomFormData. Isso quebra os limites, então deixe-o de fora. - Sem tempo limite. Uma solicitação interrompida pode deixar o controle giratório de uma página em execução indefinidamente.
- Analisando JSON para uma resposta vazia. Um 204 não tem corpo e
json()será lançado.
Considerações finais
Buscar é simples quando você se lembra de sua regra principal: uma resposta não é o mesmo que um sucesso. Copie o pequeno auxiliar em seu projeto, adicione um tempo limite e teste seus caminhos de falha. Na próxima etapa, crie uma pequena página que carregue dados de uma API, mostre uma mensagem de erro clara e permita ao usuário cancelar uma pesquisa lenta.
Perguntas frequentes
A busca gera um erro em um 404?
Não. A busca só rejeita quando nenhuma resposta é recebida, como em uma falha de rede. Para erros de HTTP, verifique você mesmo Response.ok ou Response.status.
Como envio JSON com busca?
Defina o método como POST, adicione um cabeçalho Content-Type de application/json e passe os dados por meio de JSON.stringify como corpo.
Por que preciso de duas esperas com busca?
O primeiro é resolvido assim que os cabeçalhos de resposta chegam. O segundo espera que o corpo seja baixado e analisado, o que pode acontecer posteriormente.
Como defino um tempo limite na busca?
Passe sinal: AbortSignal.timeout(5000) nas opções. A solicitação então será rejeitada com um TimeoutError se demorar mais do que esses milissegundos.
A busca está disponível em Node.js?
Sim. O Fetch está disponível globalmente no Node.js 18 e posterior. Versões mais antigas precisam de um pacote, embora as regras CORS se apliquem apenas em navegadores.
Continue aprendendo
Precisa de ajuda com testes, WordPress ou SEO?
Ajudamos as equipes a fornecer software melhor e a expandir seus sites. Conte-nos no que você está trabalhando e sugeriremos um próximo passo claro.
Mais guias sobre testes, IA e desenvolvimento moderno
Gostou deste artigo? Escolha um tópico e vá direto para nossos tutoriais mais recentes.
Explicação das alucinações de IA: por que os modelos de linguagem inventam as coisas e como reduzi-las
Explicação das alucinações de IA: o que são, por que os modelos de linguagem as produzem, tipos comuns, como reduzi-las com aterramento e instruções…
Leia o artigo →DevOpsVariáveis de ambiente explicadas: arquivos .env, segredos e configuração bem feitos
Variáveis de ambiente explicadas com exemplos de Python que executamos: leitura e configuração, por que cada valor é uma string, arquivos .env, hera…
Leia o artigo →Desenvolvimento de softwareExplicação da limitação de taxa de API: algoritmos, cabeçalhos e tratamento de erros 429
Limitação de taxa de API explicada com uma simulação que executamos: token bucket, janela fixa, janela deslizante, 429 respostas, cabeçalhos de limi…
Leia o artigo →Automação de testesZombando em Python: unittest.mock, patch e os erros que fazem os testes mentirem
Zombaria em Python com unittest.mock, testado: Mock e return_value, side_effect, patch onde um nome é usado, especificação e autospec, zombaria de d…
Leia o artigo →Teste de softwareCobertura de código explicada: cobertura de linha versus filial e o que 100% realmente significa
Cobertura de código explicada com uma execução cobertura.py real: cobertura de linha, ramal e condição, leitura de um relatório, por que 100% de cob…
Leia o artigo →Bancos de dados e SQLDELETE vs TRUNCATE vs DROP em SQL: diferenças, reversão e quando usar cada um
DELETE vs TRUNCATE vs DROP explicado com SQL testado: o que cada um remove, rollback, aciona, redefinição de identidade, velocidade e como PostgreSQ…
Leia o artigo →Bancos de dados e SQLExibições SQL explicadas: crie, use e evite as armadilhas, com exemplos
Visualizações SQL explicadas com consultas que executamos: criação de uma visualização, resultados ao vivo, ocultação de colunas, desempenho, visual…
Leia o artigo →Desenvolvimento de softwareInterface TypeScript vs tipo: diferenças reais, testadas com o compilador
Interface TypeScript versus tipo, verificada com o compilador real: o que ambos podem fazer, o que apenas um pode fazer, mesclagem de declarações, e…
Leia o artigo →Desenvolvimento de softwarePython *args e **kwargs explicados: funções flexíveis com exemplos claros
Python *args e **kwargs explicados com o código que executamos: empacotamento e descompactação, ordem dos parâmetros, argumentos somente de palavras…
Leia o artigo →Desenvolvimento de softwareFunções Python Lambda: sintaxe, usos reais e quando não usá-los
Funções lambda do Python explicadas com o código que executamos: sintaxe, classificação com chave, mapa e filtro, fechamentos, armadilha de ligação …
Leia o artigo →Inteligência artificialO que são agentes de IA? Como eles funcionam, com um loop de agente simples que você pode executar
O que são agentes de IA? Um guia simples para o loop do agente, ferramentas, memória e proteções, com um pequeno loop Python que executamos, riscos …
Leia o artigo →DevOpsMonitoramento versus observabilidade: a verdadeira diferença, com logs, métricas e rastreamentos
Explicação do monitoramento versus observabilidade: falhas conhecidas e desconhecidas, logs, métricas e rastreamentos, um passo a passo do incidente…
Leia o artigo →DevOpsDocker Volumes vs Bind Mounts: persista os dados do contêiner da maneira certa
Volumes Docker versus montagens de ligação explicadas: por que os dados do contêiner desaparecem, volumes nomeados, montagens de ligação, tmpfs, exe…
Leia o artigo →Automação de testesTDD vs BDD: principais diferenças, um recurso criado de ambas as maneiras e quando usar cada um
TDD vs BDD explicado com um recurso de desconto construído em ambos os sentidos: refatoração vermelho-verde com o código que executamos, cenários da…
Leia o artigo →Teste de softwareTeste de aceitação do usuário (UAT): processo, lista de verificação e exemplos reais
Explicação do teste de aceitação do usuário: quem o executa, como ele difere do controle de qualidade, um processo de sete etapas, um modelo de caso…
Leia o artigo →Bancos de dados e SQLValores SQL NULL explicados: IS NULL, COALESCE, NULLIF e as armadilhas a serem evitadas
Valores SQL NULL explicados com consultas que executamos: lógica de três valores, IS NULL, COALESCE, NULLIF, como agregações, junções e classificaçã…
Leia o artigo →Bancos de dados e SQLInstrução SQL CASE WHEN: sintaxe, exemplos reais e erros comuns
SQL CASE WHEN explicado com consultas que executamos: formulários simples e pesquisados, ordem de condição, pivôs com SUM, truques COUNT, classifica…
Leia o artigo →Desenvolvimento de softwareO que é JWT? JSON Web Tokens explicados com um exemplo prático
O que é JWT? JSON Web Tokens explicados: as três partes, um token construído e adulterado no código que executamos, JWT vs sessões, armazenamento, t…
Leia o artigo →Desenvolvimento de softwareLoop de eventos JavaScript explicado: pilha de chamadas, microtarefas e temporizadores com exemplos
O loop de eventos JavaScript explicado com o código que executamos: pilha de chamadas, filas de tarefas e microtarefas, por que setTimeout 0 não é i…
Leia o artigo →Desenvolvimento de softwareGeradores Python e rendimento explicado: economize memória com exemplos reais
Geradores Python e rendimento explicados com o código que executamos: como eles pausam e reiniciam, medem economia de memória, pipelines, sequências…
Leia o artigo →Inteligência artificialO que são incorporações? Similaridade de vetores e cossenos explicada de forma simples
O que são incorporações? Um guia em linguagem simples para vetores, similaridade de cossenos e pesquisa semântica, com um pequeno exemplo que execut…
Leia o artigo →DevOpsImplantação azul-verde vs canário: diferenças, compensações e como escolher
Explicação da implantação azul-verde versus canário: como cada um funciona, custo, risco e reversão, agrupamento estável de usuários que testamos, m…
Leia o artigo →Automação de testesTestes instáveis: o que os causa e como corrigi-los para sempre
Testes instáveis explicados com demonstrações que executamos: as principais causas, como confirmar e diagnosticar uma, soluções adequadas para tempo…
Leia o artigo →Teste de softwareTeste de carga versus teste de estresse: diferenças, métricas e exemplos k6
Teste de carga versus teste de estresse explicado: o que cada um prova, testes de pico e absorção, as métricas que importam, por que as médias engan…
Leia o artigo →Teste de softwareCaso de teste versus cenário de teste: principais diferenças, exemplos e quando usar cada um
Caso de teste vs cenário de teste explicado: definições claras, uma tabela lado a lado, um recurso de redefinição de senha retirado de cenários para…
Leia o artigo →Bancos de dados e SQLOtimização de consultas SQL: leia planos de execução e corrija consultas lentas, com intervalos
Otimização de consulta SQL testada em um milhão de linhas: leia planos de execução, adicione os índices corretos, corrija filtros não sargáveis, use…
Leia o artigo →Bancos de dados e SQLSQL UNION vs UNION ALL: diferenças, exemplos e desempenho testado
SQL UNION vs UNION ALL explicado com consultas que executamos: duplicatas, as regras que ambos seguem, um bug de dados real, desempenho medido, INTE…
Leia o artigo →Desenvolvimento de softwareTutorial da API JavaScript Fetch: GET, POST, tratamento de erros e tempos limite
Um tutorial da API JavaScript Fetch testado em um servidor local: GET e POST, por que 404 não lança, um auxiliar reutilizável, strings de consulta, …
Leia o artigo →Desenvolvimento de softwareManipulação de arquivos Python: leitura, gravação, CSV, JSON e pathlib com exemplos
Manipulação de arquivos Python explicada com código que executamos: modos abertos, com, leitura de arquivos grandes, CSV, JSON, pathlib, arquivos bi…
Leia o artigo →Desenvolvimento de softwareGit merge vs rebase: diferenças, exemplos e quando usar cada um
Git merge vs rebase explicado com saída real do log, uma tabela comparativa, a regra de ouro do rebase e um fluxo de trabalho seguro para equipes.
Leia o artigo →Desenvolvimento de softwareList comprehension em Python: sintaxe, exemplos e quando evitar
List comprehension em Python explicada: sintaxe, filtros, if-else, laços aninhados, tempos medidos e quando um laço for comum é a melhor escolha.
Leia o artigo →Bancos de dados e SQLSQL JOIN explicado com exemplos (Inner, Left, Right, Full)
Entenda os joins SQL passo a passo com tabelas e consultas de exemplo: INNER, LEFT, RIGHT, FULL, CROSS e SELF, além de erros comuns e dicas de desem…
Leia o artigo →