0

I'm making a very simple authenticated website for learning giving users the ability to create an account log in and view content.

The issue is not seeing the registered users on the home page (as a test) after a successful post registration. After the post, I am redirecting the user back to the home page and the get route runs a postgres function using node-postgres module to retrieve all of the users in the database and returns them. That doesn't seem to be firing. Yet, when I run the same function in my database, I do see the new user.

What's weird is that when I hit enter on the home route in the browser afterwards, the new user does pop up. So I'm really not sure if this is a caching thing or not understanding promises correctly (I've just started getting into this) or something else.

I have tried using callbacks instead of promises as shown on here: https://node-postgres.com/features/queries to see if it makes a difference. Other than that, I've added log statements to see if the promise actually resolves or rejects. But it seems to always resolve so I'm really unsure what's going on here.

<!-- register.ejs -->
<%- include('partials/header') %>
<div class="container mt-5">
  <h1>Register</h1>

  <div class="row">
    <div class="col-sm-8">
      <div class="card">
        <div class="card-body">

          <!-- Makes POST request to /register route -->
          <form action="/register" method="POST">
            <div class="form-group">
              <label for="email">Email</label>
              <input type="email" class="form-control" name="username">
            </div>
            <div class="form-group">
              <label for="password">Password</label>
              <input type="password" class="form-control" name="password">
            </div>
            <button type="submit" class="btn btn-dark">Register</button>
          </form>

        </div>
      </div>
    </div>
  </div>
</div>
<%- include('partials/header') %>
\\index.js (in ./db)
const {
    Pool
} = require('pg');

const pool = new Pool({
    database: 'secrets'
});


module.exports = {
    query: (text, params, callback) => {
        return pool.query(text, params, callback)
    }
};
//jshint esversion:6

/* Imports
 * ================================================================================ */
const express = require('express');
const bodyParser = require('body-parser');
const db = require('./db');
const util = require('util');

/* App setup
 * ================================================================================ */
const app = express();
app.disable('etag');
const port = 3000;

app.use(express.static(util.format("%s/%s", __dirname, 'public')));
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({
    extended: true
}));

/* Routes
 * ================================================================================ */

// Get request 
app.get("/", function (req, res, next) {
    db.query('SELECT * FROM dbo.usp_SelectUsers()')
        .then(function(dbResult) {
            console.log(dbResult.rows);
            res.send(dbResult.rows);
        }, (reason) => {
            console.log("Not fulfilled :(");
        }).catch(_err => next(_err));
});

// Post request for registration
app.post("/register", function (req, res, next) {
    const queryText = 'SELECT dbo.usp_CreateUser($1, $2)';
    const queryValues = [req.body.username, req.body.password];
    db.query(queryText, queryValues)
        .then(res.redirect("/"))
        .catch(err => next(err))
});
CREATE OR REPLACE FUNCTION dbo.usp_SelectUsers()
  RETURNS TABLE (User_ID INTEGER, User_Name VARCHAR(100)) AS
$func$
BEGIN
    RETURN QUERY
    SELECT u.User_ID
        ,u.User_Name
    FROM dbo.User u
    ;
END
$func$  LANGUAGE plpgsql;

Expected result is to see new users in database and displayed on home page ("/") after successful post without having to refresh the page again.

  • At least for me this is very hard to debug with these code samples. Your backend code looks find imho. So you are just printing the results in json/text at the moment? Maybe the `/` is cached ? Are there any errors in the development tools from Firefox/Chrome? It also would make sense to post the pgsql functions. – madflow Jun 20 '19 at 17:55
  • @madflow thanks for your feedback - I have added more code above showing html form for registration along with postgres sql function that I am using. I have ran that in the database and as far as I can tell, it's working the way it should. And yes I am printing results in JSON and not seeing any errors in console. As a side note in the network section I was seeing a 304 though when the redirect occurs after the post so it really doesn't seem to be calling my function – hBomberman91 Jun 20 '19 at 18:10
  • Just for lulz - can you try `app.disable('etag');` like desribed here: https://stackoverflow.com/questions/18811286/nodejs-express-cache-and-304-status-code – madflow Jun 20 '19 at 19:47
  • I've added that in but didn't help much actually - also included in above code. – hBomberman91 Jun 20 '19 at 19:58
  • So, one thing I just played around with is to add the same inserting logic that my create user function does at the beginning of dbo.usp_SelectUsers() to see whether or not it's an issue with the procedure being called or something else. And when I ran the experiment, after registering a user that I ran into a primary key violation (User_ID is PK here). And what my createUser function does is to get the latest user in the User table and add 1. So I am now under the impression that the get request occurs before the database call completes... How can I ensure this does not happen? – hBomberman91 Jun 20 '19 at 21:50
  • I think I was definitely on point when I mentioned that the get request occurred before the database call completed... I have adjusted the post code to use `async/await` and everything works as it should now. To me it seemed natural to do async / await but can someone perhaps explain the technicalities? – hBomberman91 Jun 21 '19 at 00:58

1 Answers1

0

I have updated my registration code to use async / await as follows and this fixed everything for me. I realized that the issue I was having previously is that the post did not fully complete before the database call to retrieve the the list of users were made (ie: database did not yet have the new user when calling dbo.usp_SelectUsers).

app.post("/register", async (req, res, next) => {
    try {
        const queryText = 'SELECT dbo.usp_CreateUser($1, $2)';
        const queryValues = [req.body.username, req.body.password];
        const results = await db.query(queryText, queryValues);
        res.redirect("/login");
    } catch (err) {
        throw err;
    }
});

As a side note, I have read that async / await is also much better to use nowadays and this fix added onto the pluses. Please see the following article for reference: https://hackernoon.com/6-reasons-why-javascripts-async-await-blows-promises-away-tutorial-c7ec10518dd9