Programação II Consumo de APIs fetch e axios

Consumo de APIs com fetch e axios

Nesta página você aprende, de forma passo a passo, como o front-end conversa com uma API REST usando fetch (nativo do navegador) e axios (biblioteca externa). Ela também serve como roteiro para a aula expositiva.

Revisão rápida: o que a página anterior ensinou

Na página anterior (API REST) você construiu uma API em Node.js + Express, com rotas como GET /tarefas, POST /tarefas, PUT /tarefas/:id e DELETE /tarefas/:id, retornando dados em JSON.

Agora o foco é o outro lado da comunicação: como o front-end envia requisições HTTP para essa API e exibe as respostas na interface.

Lembrete essencial:

  • A API REST organiza o back-end em recursos (ex.: /tarefas).
  • Cada recurso usa verbos HTTP (GET, POST, PUT, DELETE).
  • A resposta vem com status code (200, 201, 400, 404, 500...).
  • O formato padrão de dados será JSON.

Se ainda estiver inseguro sobre rotas, verbos HTTP ou status codes, volte primeiro para a página de API REST e revise os exemplos antes de seguir com esta.

1. Consumindo APIs com fetch

A função fetch é nativa do navegador e permite fazer requisições HTTP em JavaScript sem instalar nenhuma biblioteca. Ela retorna uma Promise com a resposta.

1.1 Primeiro exemplo: GET simples (listar tarefas)

Suponha que sua API (da página anterior) esteja rodando em http://localhost:3000 e tenha a rota GET /tarefas. O código abaixo busca a lista de tarefas e mostra no console.

<script>
async function carregarTarefas() {
  try {
    const resposta = await fetch('http://localhost:3000/tarefas');

    if (!resposta.ok) {
      // resposta HTTP com erro (404, 500, etc.)
      throw new Error('Erro na requisição: ' + resposta.status);
    }

    const dados = await resposta.json();
    console.log('Tarefas:', dados);
  } catch (erro) {
    console.error('Falha ao carregar tarefas:', erro.message);
  }
}

// chama a função quando a página carregar
carregarTarefas();
</script>
await fetch(url)
Envia a requisição para a URL da API.
resposta.ok
Indica se o status está na faixa 200–299.
resposta.json()
Converte o corpo da resposta de JSON para objeto JavaScript.

1.2 Exibindo o resultado na tela

A seguir, um exemplo que preenche uma lista HTML com as tarefas retornadas pela API.

<ul id="lista-tarefas"></ul>

<script>
async function carregarTarefas() {
  const lista = document.querySelector('#lista-tarefas');
  lista.innerHTML = '<li>Carregando...</li>';

  try {
    const resposta = await fetch('http://localhost:3000/tarefas');
    if (!resposta.ok) {
      throw new Error('HTTP ' + resposta.status);
    }

    const tarefas = await resposta.json();

    if (tarefas.length === 0) {
      lista.innerHTML = '<li>Nenhuma tarefa cadastrada.</li>';
      return;
    }

    lista.innerHTML = '';
    for (const tarefa of tarefas) {
      const li = document.createElement('li');
      li.textContent = `#${tarefa.id} - ${tarefa.titulo}`;
      if (tarefa.concluida) {
        li.style.textDecoration = 'line-through';
      }
      lista.appendChild(li);
    }
  } catch (erro) {
    lista.innerHTML = '<li>Erro ao carregar tarefas.</li>';
    console.error(erro);
  }
}

carregarTarefas();
</script>

1.3 Enviando dados com fetch (POST)

Para criar uma nova tarefa via POST, usamos fetch com opções: method, headers e body.

<form id="form-tarefa">
  <input type="text" id="titulo" placeholder="Título da tarefa">
  <button type="submit">Adicionar</button>
</form>

<script>
const form = document.querySelector('#form-tarefa');

form.addEventListener('submit', async (event) => {
  event.preventDefault();

  const titulo = document.querySelector('#titulo').value.trim();

  if (!titulo) {
    alert('Digite um título!');
    return;
  }

  try {
    const resposta = await fetch('http://localhost:3000/tarefas', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ titulo })
    });

    if (!resposta.ok) {
      throw new Error('Erro ao criar tarefa: ' + resposta.status);
    }

    const novaTarefa = await resposta.json();
    console.log('Criada:', novaTarefa);
    form.reset();
  } catch (erro) {
    console.error(erro);
    alert('Não foi possível criar a tarefa.');
  }
});
</script>

Observe que o formato do body enviado no fetch precisa coincidir com o que o back-end espera (mesmos nomes de campos e JSON válido).

2. Consumindo APIs com axios

axios é uma biblioteca que simplifica requisições HTTP. Ele funciona tanto no navegador quanto no Node.js, e já configura automaticamente os cabeçalhos mais comuns quando usamos JSON.

2.1 Como incluir axios na página

Para usar no navegador sem build, basta adicionar o link do CDN no seu HTML:

<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>

2.2 GET com axios

O exemplo abaixo faz a mesma consulta de tarefas, agora com axios.

<script>
async function carregarTarefasComAxios() {
  try {
    const resposta = await axios.get('http://localhost:3000/tarefas');
    console.log('Tarefas (axios):', resposta.data);
  } catch (erro) {
    console.error('Erro ao buscar com axios:', erro);
  }
}

carregarTarefasComAxios();
</script>
axios.get(url)
Retorna uma Promise com um objeto de resposta.
resposta.data
Já traz o corpo da resposta convertido (JSON → objeto).

2.3 POST com axios

Aqui, criamos uma nova tarefa com axios.post.

<script>
async function criarTarefaAxios(titulo) {
  try {
    const resposta = await axios.post(
      'http://localhost:3000/tarefas',
      { titulo } // axios transforma em JSON automaticamente
    );

    console.log('Criada (axios):', resposta.data);
  } catch (erro) {
    console.error('Erro ao criar com axios:', erro.response?.data || erro.message);
  }
}
</script>

axios facilita o trabalho com JSON e tratamento de erros, mas os conceitos de rota, verbo e status continuam os mesmos.

3. Tratamento de erros no consumo de APIs

Tanto em fetch quanto em axios, é essencial tratar erros: conexão recusada, rota errada, dados inválidos ou respostas 4xx/5xx.

3.1 Estratégia básica

  • Verificar o status code (resposta.ok em fetch, erro.response.status em axios).
  • Exibir mensagens amigáveis para o usuário (alert, mensagem na tela).
  • Registrar detalhes no console para facilitar o debug.

3.2 Exemplo com axios

try {
  const resposta = await axios.get('http://localhost:3000/tarefas/999');
  console.log(resposta.data);
} catch (erro) {
  if (erro.response) {
    console.log('Status:', erro.response.status);
    console.log('Dados de erro:', erro.response.data);
  } else {
    console.log('Erro de rede ou configuração:', erro.message);
  }
}

Repare que, se a API retornar 404, o código do front-end consegue identificar esse status e, por exemplo, exibir uma mensagem “Tarefa não encontrada”.

4. Bloco de exercícios

Os exercícios a seguir revisam o que foi visto na página de API REST e nesta página de consumo de APIs.

4.1 Exercícios conceituais

  1. Explique, com suas palavras, a diferença entre recurso e rota em uma API REST.
  2. Descreva o papel dos métodos GET, POST, PUT e DELETE no CRUD.
  3. Dê dois exemplos de situações em que a API deve retornar 400 e dois exemplos para 404.
  4. O que significa dizer que uma API retorna dados em JSON? Por que isso é útil no front-end?

4.2 Exercícios práticos com fetch

  1. Crie uma página HTML que busque a lista de tarefas da rota GET /tarefas usando fetch e exiba os títulos em uma lista ordenada.
  2. Adapte o exemplo anterior para exibir, ao lado de cada tarefa, um texto (concluída) ou (pendente) com base no campo concluida.
  3. Implemente um formulário para criar novas tarefas com fetch + POST. Depois de criar, recarregue a lista automaticamente.
  4. Faça a página exibir uma mensagem amigável quando a API estiver offline (por exemplo, servidor desligado).

4.3 Exercícios práticos com axios

  1. Refaça a leitura de tarefas (GET) usando axios ao invés de fetch.
  2. Implemente um botão “Excluir” para cada tarefa que dispare um DELETE com axios para a rota /tarefas/:id.
  3. Crie uma função que atualize o título de uma tarefa usando PUT com axios, lendo o novo título de um campo de texto.

5. Desafio (nível mais difícil)

Este desafio integra o conteúdo de REST + Express com o de consumo de APIs.

Desafio: painel de tarefas completo

Implemente uma página única que funcione como um mini painel de tarefas para a API da disciplina.

  • Exiba a lista de tarefas carregada da API (GET /tarefas), com título e status (concluída/pendente).
  • Permita criar novas tarefas (POST /tarefas) a partir de um formulário.
  • Inclua um botão “Concluir” que atualize uma tarefa para concluida: true usando PUT /tarefas/:id.
  • Adicione um botão “Excluir” que remova tarefas via DELETE /tarefas/:id.
  • Exiba mensagens claras de erro para casos como: servidor offline, tarefa não encontrada e validação de título vazio.

Você pode escolher usar apenas fetch, apenas axios ou combinar os dois (por exemplo, GET com fetch e modificações com axios). O importante é manter o código organizado e as mensagens claras.

6. Como isso entra no projeto do semestre

No projeto de Programação II você está desenvolvendo uma aplicação web completa. O conteúdo desta página será usado na fase de integração entre front-end e API do projeto.

6.1 Ponto de partida

  • O backend do projeto expõe uma API REST própria (rotas, verbos e status bem definidos).
  • O frontend precisará consumir essa API para listar, criar, atualizar e remover recursos.

6.2 Como você vai aplicar na prática

  • Criar serviços de API em JavaScript (funções como buscarUsuarios(), criarPedido(), atualizarProduto()) usando fetch ou axios.
  • Ligar esses serviços aos componentes de interface: formulários, tabelas, botões de ação, telas de detalhes.
  • Tratar respostas e erros para exibir feedback ao usuário (mensagens de sucesso, alertas de falha, campos com erro).
  • Documentar as rotas consumidas no README do projeto, descrevendo verbos, URLs e exemplos de JSON enviados/recebidos.

Quanto mais organizado estiver o consumo de APIs agora (funções reutilizáveis, mensagens claras e boas práticas de status), mais fácil será evoluir o projeto para incluir autenticação, filtros, paginação e outras funcionalidades.