2
respostas

Erro no async/await: Uncaught (in promise) ReferenceError: Cannot access 'listaClientes' before initialization

Boa tarde.

Fiz o async/await no forEach dentro do renderiza() em exibe-clientes.js, mas agora aparece a mensagem de erro abaixo:

Uncaught (in promise) ReferenceError: Cannot access 'listaClientes' before initialization

at renderiza (exibe-clientes.js:50)

at exibe-clientes.js:56

Eu coloquei o projeto no GitHub, mas não sei como compartilhar. Ele é público. Segue meu usuário e o nome dele no GitHub (não sei se só isso basta para localizarem, ou se tem que enviar algum link): torezani89/crud_javascript_assincrono

2 respostas

Oi Bruno!

Vamos dar uma olhada no seu código em exibe-clientes.js:

function renderiza() {
    const listaClientes = listaClientes()
    listaClientes.forEach(element => {
        tabela.appendChild(criaNovaLinha(element.nome, element.email, element.id))
    });
}

Você está criando uma nova const chamada listaClientes para armazenar o resultado, entretanto, já existe uma função com o nome listaClientes. O conflito de nomes faz com que o javascript utilize somente a variável declarada no escopo, ou seja, a função listaClientes() "deixa de existir".

Apesar de serem "tipos" diferentes, na realidade tudo que declaramos, até mesmo classes e funções, são variáveis. Sendo assim, é preferível não utilizar nomes iguais, mesmo em tipos diferentes, para evitar comportamentos inesperados, como visto neste caso.

Uma solução simples é somente trocar o nome da variável listaClientes para resultadoListaClientes, por exemplo.

function renderiza() {
    const resultadoListaClientes = listaClientes()
    resultadoListaClientes.forEach(element => {
        tabela.appendChild(criaNovaLinha(element.nome, element.email, element.id))
    });
}

Esse novo código conserta o problem anterior, mas agora há um novo erro: Erro de tipo indicando que resultadoListaClientes.forEach não é uma funçãoO método .forEach é utilizado em arrays, portanto o erro acima nos indica que resultadoListaClientes não é um array.

Ao adicionar um simples console.log(resultadoListaClientes), o resultado é o seguinte:

Console do navegador mostrando que resultadoListaClientes é uma Promise Isso acontece porque a função listaClientes() retorna uma Promise e que deve ser tratada com o .then() como visto na aula ou com async e await.

No caso do .then(), é necessário que os comandos desejados estejam dentro do .then(), desta maneira:

function renderiza() {
  listaClientes().then((resultadoListaClientes) => {
    console.log(resultadoListaClientes);
    resultadoListaClientes.forEach((element) => {
      tabela.appendChild(criaNovaLinha(element.nome, element.email, element.id));
    });
  });
}

Desta forma, o resultadoListaPacientes entra na cadeia de Promises e consegue ser utilizado quando listaClientes() for resolvido, ou seja, retornar um valor real.

Se quiser utilizar async e await, é necessário tornar a função renderiza assíncrona adicionando a palavra async antes de function. Depois, basta "aguardar" que a Promise devolvida por listaClientes() termine e devolva a lista de clientes.

// transformando em async
async function renderiza() { 
  const resultadoListaClientes = await listaClientes(); // aguardando a Promise listaClientes()

  //executando código síncrono
  resultadoListaClientes.forEach((element) => {
    tabela.appendChild(criaNovaLinha(element.nome, element.email, element.id));
  });
}

Desta forma, conseguimos escrever um código que parece síncrono, mas que espera resultados assíncronos serem recebidos antes de seguir em frente.

Olá Eduardo,

Funcionou. Utilizei o asyn/await da forma como você disse.

Mas Eduardo, ainda fiquei com uma dúvida. Quando eu tento usar o forEach diretamente na função listaClientes() ao invés de declará-la numa variável dentro do escopo, não funciona:

async function renderiza() {
    // const resultadolistaClientes = await listaClientes()
    await listaClientes().forEach(element => {
        tabela.appendChild(criaNovaLinha(element.nome, element.email, element.id))
    });
}

renderiza()

![](Insira aqui a descrição dessa imagem para ajudar na acessibilidade )