Ivan Taccadoli
Ivan Taccadoli

Reputation: 183

Node js render with data from database

I have my index.js like this

var express = require('express');
var app = express();

var list = require('./data').list;

// [...] 

app.get('/', function (req, res) {
  res.render('home',{
      list: list,
    });
});

and data.js that should ask the database server for data

const { Pool, Client } = require('pg')

var list = [];

const pool = new Pool({
  connectionString: '...',
})
pool.query('select * from list', (err, res) => {
  if(res){
    list = res.rows;
  }
  pool.end()
})

exports.list = list;

The problem is that when the page is rendered the list is empty and the database call happens after the page render. Is there a way to avoid this?

Upvotes: 0

Views: 1190

Answers (2)

Olian04
Olian04

Reputation: 6882

pool.query is an asyncronous function. You can solve your issue in many different ways, i would convert your db logic to a function that returns a promise. Then turn your HTTP handler into an async handler, and await the "promise of data" from "data.js". Like this:

// index.js
const express = require('express');
const app = express();

const { getList } = require('./data');

app.get('/', async (req, res) => {

  res.render('home', {
    list: await getList(),
  });
});
// data.js
const { Pool } = require('pg');

exports.getList = () => new Promise((resolve) => {
  const pool = new Pool({
    connectionString: '...',
  });
  pool.query('select * from list', (err, res) => {
    if (res) {
      resolve(res.rows);
    }
    pool.end();
  });
});

Upvotes: 2

José Luna
José Luna

Reputation: 69

You could separate into controllers those files like:

first create a controller and exporting the functions for example your data.js:

exports.ListFunction= async function (req, res, next) {
var list = [];

const pool = new Pool({
  connectionString: '...',
})
await pool.query('select * from list', (err, res) => {
  if(res){
    list = res.rows;
//here i save the list variable so it can be used in other files
    req.list= list;
//next() call the next function.

  }
  pool.end();
next();
})
}

Then create a controller to render the page and pass the req.list variable as a parameter

exports.RenderHome = function(req, res){
res.render('home',{
      list: req.list,
    });

}

finally in your index.js

//import your controllers
var list= require('./listController')
var home= require('./renderHome')
//call each function from the controllers
app.get('/', list.ListFunction, home.RenderHome);

I think this is the best way to manage data before sending it to the client.

Upvotes: -1

Related Questions