Capítulo 22
Pedidos à rede
4 min de leitura 654 palavras 1 gravura
Até agora o JavaScript lia o que já estava no HTML. Às vezes a lista mora em outro arquivo. Um pedido à rede busca esse arquivo depois que a página abriu. O nome antigo disso é AJAX; o verbo moderno no navegador é fetch.
Neste capítulo o pedido é local: oficinas.json na mesma pasta. Não chame API pública ainda. Isso fica para o capítulo 23.
O exemplo está em exemplos/22-ajax/. Não abra pelo disco (file://). O navegador bloqueia fetch nesse modo. Sirva em 127.0.0.1.
Trabalhe na cópia inicio desta etapa. Leia e digite o código indicado; mude apenas uma coisa. Antes de recarregar, escreva o resultado que espera. Depois compare com a referência completa ao lado. Se algo falhar, confira primeiro o arquivo salvo e o caminho aberto.
O que você vai aprender
- Pedir um arquivo com
fetche ler JSON. - Comparar
.thencomasync/await. - Tratar falha com
try/catch. - Distinguir
file://dehttp://127.0.0.1.
JSON na pasta da oficina
JSON (JavaScript Object Notation) é texto com cara de objeto. Aspas duplas nas chaves. Sem funções. Sem comentários.
[
{ "nome": "Cerâmica", "dia": "sábado" },
{ "nome": "Xilogravura", "dia": "domingo" },
{ "nome": "Fotografia", "dia": "quarta" }
]
O arquivo chama oficinas.json. O script pede esse nome relativo à página.
const resposta = await fetch("oficinas.json");
const oficinas = await resposta.json();
fetch devolve uma promessa: um valor que ainda vai chegar. await pausa a função async até a resposta vir. resposta.json() lê o corpo e monta o array.
Se a página foi aberta como arquivo, o pedido costuma falhar. A mensagem de erro do exemplo avisa para usar o servidor.
Erro comum: duplo clique em index.html e achar que o JSON “não existe”. Ele existe no disco. O que falta é HTTP local.

Sirva em 127.0.0.1
Na pasta curso deste material:
python -m http.server 8769 --bind 127.0.0.1 --directory curso
Visite http://127.0.0.1:8769/exemplos/22-ajax/. Encerre o servidor com Ctrl+C.
127.0.0.1 é esta máquina. Não use 0.0.0.0. Não publique este JSON.
Pare e experimente. Abra a mesma pasta pelo Explorador (barra começando com file://) e recarregue. A lista deve falhar. Volte ao endereço 127.0.0.1 e a lista deve aparecer.
then versus async/await
As duas formas esperam a mesma promessa. A de .then encadeia funções. A de await parece código em fila.
fetch("oficinas.json")
.then((resposta) => {
if (!resposta.ok) throw new Error("não achei o JSON");
return resposta.json();
})
.then((oficinas) => {
oficinas.forEach((oficina) => {
const item = document.createElement("li");
item.textContent = `${oficina.nome} — ${oficina.dia}`;
document.getElementById("lista").append(item);
});
})
.catch((falha) => {
console.error(falha);
});
A versão do exemplo usa async / await e try / catch:
async function carregar() {
const lista = document.getElementById("lista");
const erro = document.getElementById("erro");
try {
const resposta = await fetch("oficinas.json");
if (!resposta.ok) throw new Error("não achei o JSON");
const oficinas = await resposta.json();
oficinas.forEach((oficina) => {
const item = document.createElement("li");
item.textContent = `${oficina.nome} — ${oficina.dia}`;
lista.append(item);
});
} catch (falha) {
erro.hidden = false;
erro.textContent = "Não deu para ler o JSON. Use o servidor em 127.0.0.1.";
console.error(falha);
}
}
carregar();
await só funciona dentro de async function. Lá em cima do arquivo, fora de função, este volume não usa await.
resposta.ok é falso em 404 (arquivo errado). Sem esse if, você tentaria ler HTML de erro como se fosse JSON.
O que catch segura
Rede falhou, arquivo sumiu, JSON malformado: tudo cai no catch. Mostre uma frase na página. Não deixe a falha só no console.
Não peça ainda https://... de um site público. Primeiro o JSON da pasta tem que listar as três oficinas. Quando isso estiver firme, o capítulo 23 usa uma API só como fonte de imagens.
Erro comum: concatenar o endereço file:///B:/.../oficinas.json na mão. fetch relativo ("oficinas.json") basta quando a página e o JSON estão no mesmo diretório servido por HTTP.
Atividades
- O que
await resposta.json()devolve neste exemplo? - Por que
carregarprecisa serasync? - Qual endereço você cola na barra para este exercício funcionar?
- Renomeie o JSON para
agenda.jsonsem mudar o script. O que a página deve mostrar?
Respostas comentadas
- Um array de três objetos, cada um com
nomeedia. A partir daí é o mesmo JavaScript do capítulo 17. - Porque ela usa
await. Semasync, o arquivo nem carrega: o navegador aponta erro de sintaxe. http://127.0.0.1:8769/exemplos/22-ajax/(a porta segue o comando que você usou). Não éfile://.- A lista vazia e o parágrafo de erro visível. O
fetchcontinua pedindooficinas.json, que não está mais nesse nome.
Referências
O arquivo completo
Referência do exemplo 22-ajax, reproduzida aqui para que você possa conferir sem sair da página.
index.html
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="utf-8"/>
<meta content="width=device-width, initial-scale=1" name="viewport"/>
<title>Pedidos à rede</title>
<link href="lab.css" rel="stylesheet"/>
<style>body{overflow-wrap:anywhere}img,input,textarea,select,iframe{max-width:100%}img{height:auto}fieldset,.cartao{min-width:0}pre{max-width:100%;overflow:auto}:focus-visible{outline:3px solid #005fcc;outline-offset:3px}.atalho-conteudo{position:absolute;left:.5rem;top:-6rem;background:white;color:#172f50;padding:.5rem;z-index:999}.atalho-conteudo:focus{top:.5rem}@media(prefers-reduced-motion:reduce){*,*::before,*::after{animation:none!important;transition:none!important;scroll-behavior:auto!important}}</style></head>
<body><a class="atalho-conteudo" href="#conteudo">Pular para o conteúdo</a><main id="conteudo" tabindex="-1">
<h1>Lista vinda de um JSON</h1>
<p>Sirva esta pasta em 127.0.0.1. Abrir pelo disco costuma bloquear o fetch.</p>
<ul id="lista"></ul>
<p class="fail" hidden="" id="erro"></p>
</main><script src="script.js"></script></body>
</html>
script.js
async function carregar() {
const lista = document.getElementById("lista");
const erro = document.getElementById("erro");
try {
const resposta = await fetch("oficinas.json");
if (!resposta.ok) throw new Error("não achei o JSON");
const oficinas = await resposta.json();
oficinas.forEach((oficina) => {
const item = document.createElement("li");
item.textContent = `${oficina.nome} — ${oficina.dia}`;
lista.append(item);
});
} catch (falha) {
erro.hidden = false;
erro.textContent = "Não deu para ler o JSON. Use o servidor em 127.0.0.1.";
console.error(falha);
}
}
carregar();