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:
O 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:
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.