Problemas com getElementById: O que devo fazer?

Não consigo ler o id “catalogo” e minha variável catalogo fica null. O que tem de errado no código abaixo?

var produtosPromise;
function leNet() {
  produtosPromise = fetch(
    `http://makeup-api.herokuapp.com/api/v1/products.json`
  );
}
leNet();
var catalogo = document.getElementById("catalogo");
var produtos;

produtosPromise.then((resp) => {
  resp.json().then((produtos) => {
    let tabela = renderTabela(produtos);
    catalogo.appendChild(tabela);
  });
});

function renderTabela(produtos) {
  let linhas = produtos.map((produto) => {
    return `<tr><td>${produto.name}</td><td>${produto.price}</td></tr>`;
  });
  return `<table>${linhas.join("")}</table>`;
}

Será que preciso fazer alguma coisa no navegador, será que é vírus, tem algum comando errado?

Atenciosamente, obrigado,
Ronaldo

e cadê o id catalogo no código que vc passou?

O id catalogo está dentro de index.html que estou te mandando agora:

<!DOCTYPE html>
<html lang="en">
  <head>
    <link rel="shortcut icon" href="" />
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Make Up Catalog</title>
    <link rel="stylesheet" href="css/style.css" />
  </head>
  <body>
    <header>
      <h1>Make Up Catalog</h1>
    </header>
    <main>
      <form class="catalog-control">
        <div class="form-control">
          <label for="filter-name">Nome:</label>
          <input type="text" id="filter-name" />
        </div>
        <div class="form-control">
          <label for="filter-brand">Marca:</label>
          <select id="filter-brand">
            <option value="">Todos</option>
          </select>
        </div>
        <div class="form-control">
          <label for="filter-type">Tipo:</label>
          <select id="filter-type">
            <option value="">Todos</option>
          </select>
        </div>
        <div class="form-control">
          <label for="sort">Ordem: </label>
          <select id="sort-type">
            <option>Melhor Avaliados</option>
            <option>Menores Preços</option>
            <option>Maiores Preços</option>
            <option>A-Z</option>
            <option>Z-A</option>
          </select>
        </div>
      </form>
      <section class="catalog"></section>
    </main>

    <div id="catalogo"></div>
  </body>
  <script src="js/app.js"></script>
</html>

Veja que app.js esta dentro de uma pasta chamada js e index.html que está sendo executado sem problema está um nivel acima da pasta js.

Um problema é a forma como vc está tratando a parte assíncrona. Vejo que vc está criando variáveis fora do escopo para receber os dados de algo que não se sabe quando será retornado (assíncrono), o que deixa o código falho sujeito a erros.

Refiz o código e coloquei uns comentários para tentar explicar:

// Função que realiza a chamada HTTP para recuperar os dados
function lerDados(callback) {
  fetch("http://makeup-api.herokuapp.com/api/v1/products.json").then((resp) => {
    // Obtém a resposta da requisição HTTP e faz a conversão para JSON
    // Em seguida invoca a função callback passando os dados recebidos
    resp.json().then((data) => callback(data));
  });
}

// Monta a string com o conteúdo html para ser renderizado na DIV
function renderTabela(produtos) {
  let linhas = produtos.map((produto) => {
    return `<tr><td>${produto.name}</td><td>${produto.price}</td></tr>`;
  });
  return `<table>${linhas.join("")}</table>`;
}

// Obtém a DIV onde a tabela será renderizada e adiciona um texto para indicar que os daados estão sendo carregados
const catalogo = document.getElementById("catalogo");
catalogo.innerText = "Loading...";

// Chama a função que recupera os dados passando uma função callback que irá receber os dados no formato json
lerDados((dados) => {
  let tabela = renderTabela(dados);
  catalogo.innerHTML = tabela;
});

1 curtida

Deu certo!!! Obrigado.

Lucas, e se eu quiser fazer o fetch de forma asincrona numa função async que codigo devo usar?

Atenciosamente,
Ronaldo

Ficaria assim:

async function lerDados() {
  return fetch("http://makeup-api.herokuapp.com/api/v1/products.json").then(
    (resp) => {
      return resp.json();
    }
  );
}

function renderTabela(produtos) {
  let linhas = produtos.map((produto) => {
    return `<tr><td>${produto.name}</td><td>${produto.price}</td></tr>`;
  });
  return `<table>${linhas.join("")}</table>`;
}

async function executar() {
  const catalogo = document.getElementById("catalogo");
  catalogo.innerText = "Loading...";

  const dados = await lerDados();
  let tabela = renderTabela(dados);

  catalogo.innerHTML = tabela;
}

executar();
1 curtida