Pular para o conteúdo
murad.guide

Além do Webdev

Capítulo 15

Carregar JSON sem depender do sucesso do pedido

6 min de leitura 1.060 palavras 1 gravura

Neste capítulo você vai conferir sucesso, vazio e falha sem retirar a agenda principal. O objetivo é terminar uma tarefa pequena e conferir seu resultado no Mirante do Mucuripe.

Seu ponto de partida

Estude depois do capítulo 14. Retome a referência se uma experiência anterior ficou alterada. Use o exemplo 15-json-com-falha do pacote anexo e copie inicio/ para uma pasta de prática fora do original. A raiz do exemplo é a referência completa desta etapa. Você não precisa copiar arquivos da etapa anterior.

Abra index.html da sua cópia no navegador e o mesmo arquivo num editor de texto simples. Para mídia, ferramenta de conferência e JSON, use o teste HTTP local explicado no README. Abrir ou testar não publica a página.

Como praticar

Leia a explicação e digite ou confira o código indicado. Mude uma coisa. Anote sua previsão antes de salvar e recarregar. Compare o resultado e investigue o erro antes de avançar. Ao terminar cada experiência, restaure somente a mudança indicada, para que a próxima parta dos valores da referência. Você pode parar depois de uma lição.

O conteúdo adicional é uma escolha

Fetch faz um pedido e retorna uma promessa, um resultado que será conhecido depois. A função async permite usar await para aguardar cada passo sem escrever o restante da ação como se o resultado já existisse. O botão inicia o pedido; a página não precisa desse carregamento para mostrar agenda e orientações. Novidades.json contém uma lista de textos fictícios. Abra por HTTP local: o navegador pode restringir pedidos a arquivos quando a página usa file. Essa diferença é parte da experiência, não um motivo para desativar proteções do navegador.

Faça na sua cópia

Abra assets/novidades.json e compare com o botão. A implementação completa está no pacote de exemplos que acompanha este volume. Confira o trecho no seu contexto antes de mudar.

[
  "Leve seu arquivo de prática.",
  "Reserve alguns minutos para conferir pelo teclado."
]

Mude uma coisa e preveja

Troque somente o primeiro texto da lista por Separe sua cópia antes de experimentar.

Anote o que espera observar antes de salvar e recarregar.

Recarregue e confira

Depois de Carregar extras, o texto novo aparece numa lista. A agenda principal já estava disponível antes.

Se não acontecer

Confira JSON válido, caminho relativo e HTTP local. Vírgula depois do último item não é aceita em JSON.

Um pedido respondido ainda pode ter falhado

Fetch não rejeita automaticamente uma resposta HTTP como 404. Response.ok permite conferir se o status está na faixa de sucesso antes de ler JSON. Depois, a implementação verifica se o resultado é uma lista de textos dentro dos limites do exercício. Não basta um arquivo ter extensão json para seu conteúdo estar correto. Array.isArray reconhece a lista e every confere cada item. A regra serve ao formato específico desta etapa, não é um validador universal de qualquer documento. A mensagem de falha indica onde continuar lendo.

Faça na sua cópia

Confira o bloco de verificação em assets/extras.js. A implementação completa está no pacote de exemplos que acompanha este volume. Confira o trecho no seu contexto antes de mudar.

const response = await fetch('assets/novidades.json');
if (!response.ok) throw new Error('Pedido recusado');
const items = await response.json();

Mude uma coisa e preveja

Troque somente o caminho do pedido por assets/nao-existe.json.

Anote o que espera observar antes de salvar e recarregar.

Recarregue e confira

O retorno explica que os extras não carregaram e aponta para agenda e orientações. A base não desaparece. Restaure o caminho.

Se não acontecer

Se a lista anterior continuar parecendo atual, confira se o retorno muda no início da ação e no tratamento de falha.

Falha e vazio não são o mesmo estado

Uma lista vazia pode ser um resultado válido: não há extras agora. Um objeto no lugar da lista ou JSON inválido é formato inesperado. Try reúne a tentativa, catch trata a falha e finally libera o botão ao terminar. TextContent cria os textos dos itens; não transforma uma entrada como em marcação. O botão fica desabilitado durante o pedido para evitar ações sobrepostas nesta experiência. Esses controles deixam claro o que aconteceu, sem prometer disponibilidade contínua. Confira estados distintos e restaure o arquivo depois de cada teste.

Faça na sua cópia

Confira tratamento, apresentação e finally no arquivo completo. A implementação completa está no pacote de exemplos que acompanha este volume. Confira o trecho no seu contexto antes de mudar.

[]

Mude uma coisa e preveja

Troque somente o conteúdo de novidades.json por [] e carregue novamente.

Anote o que espera observar antes de salvar e recarregar.

Recarregue e confira

A página diz que não há informações adicionais agora. Isso é diferente da mensagem de falha; o botão fica disponível para outra tentativa.

Se não acontecer

Se houver falha com [], confira a validação. Para testar formato inesperado, use {} noutra experiência e depois restaure a lista original.

Trecho do resultado de referência do capítulo 15

A captura mostra uma parte da referência. Abra o exemplo para conferir a página inteira. Uma experiência temporária pode produzir outra aparência; restaure os valores antes de comparar.

O carregamento completo

O arquivo assets/extras.js está pronto. Não é necessário reconstruí-lo para testar os estados. Leia a sequência com calma: preparar, pedir, conferir, apresentar ou informar falha, liberar o botão.

const load = document.querySelector('#carregar');
const result = document.querySelector('#extras');
if (load && result) {
  load.hidden = false;
  load.addEventListener('click', async () => {
    load.disabled = true;
    result.textContent = 'Carregando informações adicionais…';
    try {
      const response = await fetch('assets/novidades.json');
      if (!response.ok) throw new Error('Pedido recusado');
      const items = await response.json();
      if (!Array.isArray(items) || items.length > 20 ||
          !items.every(item => typeof item === 'string' && item.length <= 300)) {
        throw new Error('Formato inesperado');
      }
      result.replaceChildren();
      if (items.length === 0) {
        result.textContent = 'Não há informações adicionais agora. A agenda acima continua disponível.';
      } else {
        const list = document.createElement('ul');
        for (const item of items) {
          const line = document.createElement('li');
          line.textContent = item;
          list.append(line);
        }
        result.append(list);
      }
    } catch (error) {
      result.textContent = 'Não foi possível carregar os extras. Leia a agenda e as orientações acima.';
    } finally {
      load.disabled = false;
    }
  });
}

Atividades para fazer antes das respostas

Use uma nova cópia da base. Tente primeiro; depois compare seus resultados com os comentários.

  1. Teste uma lista válida alterando um texto.

  2. Teste caminho inexistente e recupere a referência.

  3. Compare [], {} e texto JSON inválido, um estado por vez.

Respostas comentadas

Compare o que você previu com o que observou. Uma solução diferente pode funcionar se mantiver o conteúdo e a tarefa acessíveis.

  1. A lista aparece somente depois da ação e contém texto criado sem interpretar HTML. A agenda não depende dessa resposta.

  2. Response.ok identifica a resposta sem sucesso; catch informa a dificuldade e mantém a leitura principal. Restaurar o caminho recupera o pedido.

  3. [] é uma lista válida vazia. {} viola o formato esperado e JSON inválido não pode ser interpretado. Os últimos dois são falhas, com botão liberado pelo finally.

Quando seguir

Você reconhece os estados do pedido e mantém conteúdo útil quando os extras não estão disponíveis. Se ainda houver dúvida, repita somente a experiência que precisa esclarecer.

O arquivo completo

Referência do exemplo 15-json-com-falha, reproduzida aqui para que você possa conferir sem sair da página.

assets/acao.js

const button = document.querySelector('#orientar');
const message = document.querySelector('#orientacao');
if (button && message) {
  button.hidden = false;
  button.addEventListener('click', () => {
    message.textContent = 'Comece pela agenda e leia a descrição da atividade.';
  });
}