Função consulta MySQL e retorna Json para o render

Galera tem uma página ejs estática, porém queria deixar ela dinâmica trazendo dados do banco de dados MySQL.

Queria fazer uma função no módulo “funcoes.js”, nessa função eu faço uma consulta no banco MySQL, gravo o resultado numa variável e retorno ela:

//Arquivo funcoes.js    
module.exports = {

   getTabela() {
            //Variável que vai receber dados da consulta
            data = {};
            //Select
            let sql = "SELECT * FROM tb_sobre";
            //Executando a consulta
            db.query(sql, (err, results, fields) => {
                //Se consulta ok
                if (results.length > 0) {
                    //Armazena dados da consulta na variável data
                    data = results;
                //Se a consulta não for ok
                } else {
                    console.log('Erro: ' + err);
                }
            });
            //Retorna variável data com dados da conulta
            return data;
        },
    }

Ao usar essa consulta no trecho da rota que faz o render deve passar como parâmetro para a página os dados:

//Importo o múdulo funcoes
const funcao = require('./funcoes');

module.exports = {

  //Rota que faz o render
  pageSite: (req, res, next) => {
    res.render('./site/index.ejs', {
      dados: funcao.getTabela()//Aqui deveria passar os dados
    });
  },

};

E lá no index.ejs recebo o dado passado pelo render:

<!-- Título -->
<div class="wow fadeInUp" data-wow-duration="1s" data-wow-delay="300ms">
     <h2><%= dados.titulo %></h2><!-- Aqui recebo um campo -->
</div>

Está vindo em branco.
Toda minha página está rodando ok, minhas rotas estão ok, acesso e consulta ao MySQL ok.

Só não estou conseguindo fazer essa forma de popular a página dinamicamente com dados vindo do MySQL.

Se eu dou um console.log para ver o que está retornando a função, me retorna:

data: [object Object]

Como faço para este objeto retornar um array ou um json por exemplo usando essas mesas estruturas ai em cima pra eu popular meu ejs?


Veja a parte 4

@javaflex, obrigado pela resposta mas… olha só até onde cheguei:

No arquivo funcoes.js onde tenho as consultas:

module.exports = () => {
    return {
        getSobre() {
            return new Promise((resolve, reject) => {
                db.query(`SELECT * FROM sobre ORDER BY cod DESC LIMIT 1`, (err, results) => {
                    if (err) {
                        return reject(err);
                    } else {
                        return resolve(results);
                    }
                });
            });
        },
    };
}

Aqui é meu arquivo de rota onde faço o render do index.ejs passando os dados recebidos da função, aqui é que está o problema agora, veja:

const funcao = require('./funcoes')();

//Variável que irá armazenar o retorno da função
var dados;

    module.exports = {

      //Router p/ index.js
      pageSite: (req, res, next) => {
        //Função que faz um select na tabela, está lá no funcao.js
        funcao.getSobre().then(data => {
          //Armazena o resultado da promisse na variável "dados"
          dados = JSON.parse(JSON.stringify(data[0]));
          console.log('001: ', dados);//Aqui a variável está ok, no console retorna um JSON
        });
        console.log('002: ', dados);//Aqui a variável perde os dados (?)
        //Renderiza index.ejs passando os dados da função acima
        res.render('./site/index', {
          dados //Na página fica como undefined (vazio)
        });
      },

    }

Olha meu console.log:

O problema:

Se eu colocar o render dentro do bloco funcao.getSobre().then(data => { funciona perfeitamente, porém eu não tenho apenas essa consulta, tenho outras tabelas que populariam outras seções da página, ou seja, terei varias funções, e tão a ideia seria armazenar o retorno dessas funções uma em cada variável diferente e lá no bloco do render utilizá-las.

Se são seções independentes na página, faz as APIs/requisições separadas, assim facilita e também melhora escalabilidade. Senao, se for dependente faz um único SELECT com joins, que além de mais prático fica mais performático.

São section tudo numa única página, conforme vou rolando a página para baixo vai aparecendo as seções, o problema é que a seção 1 são textos estáticos, a seção 2 seria um array pois popula um carrousel, a seção 3 estático, seção 4 array… por isso precisaria realizar consultas e funções distintas entende… e lá no render passar as funções em cada parâmetro, não é possível não existir nada desse tipo, fazer um único select com join não dá, me ajudem ai pessoal.

Tu nao ta usando ajax?

estou usando JavaScript com Node.JS, Express, HTML 5 e CSS, fiz a página completa e queria gora fazer uma administração para o conteúdo do site entende para deixá-lo dinâmico e para o próprio usuário poder alterar as informações da página pelo admin.

Tenta assim:

res.render('./site/index.ejs', {
      dados1: funcao.getTabela1(),
      dados2: funcao.getTabela2()
   });

bom dia, sim tentei desta forma, me retorna undefined. Se eu jogo o res.render lá dentro do funcao.getSobre().then(data => { ai da certo, só que o funcao.getSobre().then(data => { é referente a apenas a primeira função, por isso estou colocando o res.render fora dela.

Olha essa segunda alternativa, vejam se conseguem me ajudar nela, se eu conseguir retornar os dados da Promise neste “title:” mata o problema:

function getSobre() {
    return new Promise((resolve, reject) => {
        db.query(`SELECT * FROM sobre ORDER BY cod DESC LIMIT 1`, (err, results) => {
            if (err) {
                return reject(err);
            } else {
                return resolve(results);
            }
        });
    });
}

const data = {
    title: getSobre().then(data => {
        /*
         * AQUI Como faço para retornar esse "data" para o "title:"
         */
    }),
    name: 'Fabio',
    profession: 'Analista'
}
module.exports = data;

Resolvido: https://stackoverflow.com/questions/61750668/how-to-set-json-value-on-the-ejs-page