Desafio JavaScript

Buscando múltiplos recursos e tratando erros

Enunciado

Crie uma função buscarPostsDoUsuario(userId) que busca todos os posts do usuário com ID fornecido em https://jsonplaceholder.typicode.com/posts?userId={userId} e exibe os títulos. Depois, para cada post, busque os comentários em https://jsonplaceholder.typicode.com/posts/{postId}/comments e exiba a contagem de comentários. Use Promise.all para paralelizar as requisições de comentários. Trate erros de status e de rede.

Requisitos

  • Buscar posts com fetch e verificar response.ok.
  • Para cada post, buscar comentários em paralelo com Promise.all.
  • Exibir Post: [title] - Comentários: [count] para cada post.
  • Tratar erros de status e de rede com try/catch.
  • Usar JSON.stringify ou JSON.parse quando necessário (não obrigatório, mas pode ser usado para formatar).

Código inicial

async function buscarPostsDoUsuario(userId) {
  // Seu código aqui
}

buscarPostsDoUsuario(1);

Saída esperada

Post: sunt aut facere repellat provident occaecati excepturi optio reprehenderit - Comentários: 5
Post: qui est esse - Comentários: 5
Post: ea molestias quasi exercitationem repellat qui ipsa sit aut - Comentários: 5
Post: eum et est occaecati - Comentários: 5
Post: nesciunt quas odio - Comentários: 5
Post: dolorem eum magni eos aperiam quia - Comentários: 5
Post: magnam facilis autem - Comentários: 5
Post: dolorem dolore est ipsam - Comentários: 5
Post: nesciunt iure omnis dolorem tempora et accusantium - Comentários: 5
Post: optio molestias id quia eum - Comentários: 5
Ver dica

Primeiro busque os posts. Depois, use posts.map(post => fetch(...).then(res => res.json())) e Promise.all para buscar todos os comentários de uma vez. Verifique response.ok em cada requisição.

Mostrar solução
async function buscarPostsDoUsuario(userId) {
  try {
    // Busca todos os posts do usuário
    const respostaPosts = await fetch(`https://jsonplaceholder.typicode.com/posts?userId=${userId}`);
    if (!respostaPosts.ok) {
      throw new Error(`Erro HTTP ao buscar posts: ${respostaPosts.status}`);
    }
    const posts = await respostaPosts.json();

    // Cria um array de Promises para buscar comentários de cada post em paralelo
    const promessasComentarios = posts.map(async (post) => {
      const respostaComentarios = await fetch(`https://jsonplaceholder.typicode.com/posts/${post.id}/comments`);
      if (!respostaComentarios.ok) {
        throw new Error(`Erro HTTP ao buscar comentários do post ${post.id}: ${respostaComentarios.status}`);
      }
      const comentarios = await respostaComentarios.json();
      return { post, comentarios };
    });

    // Aguarda todas as requisições de comentários
    const resultados = await Promise.all(promessasComentarios);

    // Exibe os resultados
    for (const { post, comentarios } of resultados) {
      console.log(`Post: ${post.title} - Comentários: ${comentarios.length}`);
    }
  } catch (erro) {
    console.error('Erro:', erro.message);
  }
}

buscarPostsDoUsuario(1);

Passo a passo

  1. A função buscarPostsDoUsuario é assíncrona e recebe userId.
  2. Buscamos os posts do usuário com fetch e verificamos respostaPosts.ok.
  3. Convertemos a resposta para array de posts com await respostaPosts.json().
  4. Usamos posts.map para criar um array de Promises; cada Promise busca os comentários de um post.
  5. Dentro do map, verificamos respostaComentarios.ok e lançamos erro se necessário.
  6. Promise.all aguarda todas as Promises de comentários e retorna um array de resultados.
  7. Iteramos sobre os resultados e exibimos o título do post e a quantidade de comentários.
  8. O catch captura qualquer erro ocorrido durante o processo.

Por que funciona

O fetch retorna Promises, e Promise.all permite executar múltiplas requisições em paralelo, tornando o código mais rápido. Cada requisição de comentários é independente, então podemos disparar todas ao mesmo tempo. A verificação de ok garante que erros HTTP sejam tratados. O try/catch captura falhas de rede ou erros lançados.

Erros comuns

  • Não usar Promise.all: se você fizer for com await dentro, as requisições serão sequenciais, mais lentas.
  • Esquecer de verificar ok em cada requisição: um erro 404 em um post pode passar despercebido.
  • Não tratar erros dentro do map: se uma Promise rejeitar, Promise.all rejeita imediatamente; o catch externo captura, mas você perde os resultados dos outros.
  • Usar JSON.parse desnecessariamente: response.json() já faz o parse; não precisa chamar JSON.parse novamente.

Outra forma de resolver

Usar Promise.allSettled para não interromper todas as requisições se uma falhar:

const resultados = await Promise.allSettled(promessasComentarios);
for (const resultado of resultados) {
  if (resultado.status === 'fulfilled') {
    const { post, comentarios } = resultado.value;
    console.log(`Post: ${post.title} - Comentários: ${comentarios.length}`);
  } else {
    console.error('Falha ao buscar comentários:', resultado.reason.message);
  }
}

Essa forma é preferível quando você quer que todas as requisições sejam tentadas, mesmo que algumas falhem.

Saída esperada

Post: sunt aut facere repellat provident occaecati excepturi optio reprehenderit - Comentários: 5
Post: qui est esse - Comentários: 5
Post: ea molestias quasi exercitationem repellat qui ipsa sit aut - Comentários: 5
Post: eum et est occaecati - Comentários: 5
Post: nesciunt quas odio - Comentários: 5
Post: dolorem eum magni eos aperiam quia - Comentários: 5
Post: magnam facilis autem - Comentários: 5
Post: dolorem dolore est ipsam - Comentários: 5
Post: nesciunt iure omnis dolorem tempora et accusantium - Comentários: 5
Post: optio molestias id quia eum - Comentários: 5