fetch: conversando com APIs
Todo app vivo busca dados de algum lugar: previsão do tempo, cotações, mensagens. O fetch é a ponte entre o seu código e esses serviços.
Estudar esta lição interativa →De onde um app de previsão do tempo tira a temperatura? E o de notícias, as manchetes? Esses dados não estão no código do app: eles moram em servidores na internet, e o app os busca na hora. O balcão de atendimento desses servidores chama-se API: um endereço (uma URL) que, em vez de devolver uma página bonita, devolve dados crus, pensados para programas consumirem. Existem APIs públicas para quase tudo: clima, moedas, filmes, piadas.
A ferramenta do JavaScript para bater nesse balcão é o fetch (em inglês, "ir buscar"). E, como uma viagem pela internet leva tempo, ele é assíncrono, caso perfeito para o await que você acabou de aprender:
Duas viagens: o fetch(url) leva o seu pedido até a API, e a resposta volta com os dados em JSON, um texto que o .json() transforma em objeto para o seu código usar.
Repare no desenho que a resposta vem em JSON, mais uma sigla que vale conhecer: JavaScript Object Notation. É um formato de texto para transportar dados, e a graça é que ele é praticamente idêntico aos objetos e arrays que você estudou no Módulo 6, com chaves, dois-pontos e colchetes. Por isso a conversão é um passo só: await resposta.json() transforma o texto recebido num objeto de verdade, pronto para usar com ponto (dados.setup). O exemplo abaixo busca uma piada aleatória numa API pública. Rode (precisa de internet):
// fetch busca dados de uma API na internet (precisa estar online).
async function buscarPiada() {
try {
const resposta = await fetch("https://official-joke-api.appspot.com/random_joke");
// O fetch só falha de verdade quando a viagem não acontece (sem rede, domínio que
// não existe). Se o servidor responder com erro (404, 500...), a resposta chega
// normalmente: quem avisa é resposta.ok, que fica false.
if (!resposta.ok) throw new Error("O servidor respondeu com o status " + resposta.status);
const dados = await resposta.json(); // transforma em objeto
// ?. e ?? protegem o código se a API mandar um objeto sem esses campos:
console.log("Pergunta: " + (dados?.setup ?? "(a API não mandou a pergunta)"));
console.log("Resposta: " + (dados?.punchline ?? "(a API não mandou a resposta)"));
} catch (erro) {
console.log("Deu erro (você está online?):", erro.message);
}
}
buscarPiada();Requer conexão com a internet.
Dissecando o padrão, que é sempre o mesmo: await fetch(url) faz a viagem de ida e volta e entrega a resposta; await resposta.json() converte o corpo dela em objeto; e daí em diante é o JavaScript de sempre. A novidade restante é o try/catch, que estreia aqui: o código dentro do try ("tente") roda normalmente, mas, se qualquer passo falhar (sem internet, API fora do ar), em vez de o programa quebrar, a execução pula para o bloco catch ("capture"), onde você decide como reagir, por exemplo mostrando uma mensagem amigável. Com rede, é elegante; sem rede, é indispensável.
O fetch só "falha" (e leva a execução para o catch) quando a viagem nem chega a acontecer: sem internet, domínio que não existe. Se o servidor responde dizendo "não achei" (status 404) ou "tive um problema" (status 500), isso é uma resposta como outra qualquer do ponto de vista do fetch: nada é lançado. Quem avisa é a propriedade resposta.ok, que vale true para status de sucesso (200 a 299) e false para o resto. Por isso o exemplo confere if (!resposta.ok) logo depois do fetch e lança o próprio erro, que o catch então captura. Sem essa linha, o .json() tentaria ler uma página de erro como se fosse dado.
Pare um segundo e olhe o que esse pedacinho de código faz: atravessa a internet, busca dados num servidor e os traz para dentro do seu programa. Buscar dados de uma API e exibi-los na tela é, literalmente, o que a maioria dos apps do seu celular faz o dia inteiro. Com o fetch desta lição e o DOM do módulo passado, você já tem a dupla que constrói aplicações reais.