Make my db queries synchronous with with my promise based function

263 Views Asked by At

How can I make my db queries synchronous with with my promise base function? In my code, I am running 3 db operations inside 3 different functions which need to be run in order, like waterfall model. The functions are running in waterfall model but db queries inside those functions are working in asynchronous. I need to run db queries inside those function in synchronous.

In this example I am expecting in console:

1
2
3
4

But I am getting

1
3
2
4

Code:

const Promise = require('bluebird');

// DB Settings    
const dbConfig = {
    user: process.env.DBUSER,
    password: process.env.DBPWD,
    database: process.env.DBNAME,
    host: process.env.DBHOST,
    port: process.env.DBPORT,
    poolSize: 10, // max number of clients in the pool
    //poolIdleTimeout: 30000, // how long a client is allowed to remain idle before being closed
    //reapIntervalMillis: 1000 //frequency to check for idle clients within the client pool
};
const pgp = require('pg-promise')();
const db = pgp(dbConfig);

var currentStatus = '',newStatus = '';

const _updateCurrentStatus = () => new Promise((resolve, reject) => {


    const _getCurrentStatus = (_userId) => new Promise((_resolve, _reject) => {        

        console.log("1");
        let statusQuery = "SELECT status FROM users WHERE id=" + _userId;

        db.one(statusQuery).then(function (data) {
            console.log("2");
            currentStatus = data.status;
            _resolve();
        }).catch(function (error) {
            _reject(error);
        });
    });

    const _setUpdateStatus = (cStatus, nStatus) => new Promise((_resolve, _reject) => {

        if(allApproved){
            if(cStatus == 'nvd_pending'){
                //nStatus = 'finance_pending';
                newStatus = 'finance_pending';
            }else if(cStatus == 'finance_pending'){
                //nStatus = 'oracle_pending';
                newStatus = 'oracle_pending';
            }else if(cStatus == 'oracle_pending'){
                //nStatus = 'active';
                newStatus = 'active';
            }else{
                //nStatus = cStatus;
                newStatus = cStatus;
            }
        }else{
            //nStatus = 'nvd_pending';
            newStatus = 'nvd_pending';
        }
        //_resolve(nStatus);
        _resolve();

    });

    const _updateStatus = (_newStatus, _payLoad) => new Promise((_resolve, _reject) => {

        console.log("3");

        let updateuserQuery = "UPDATE users SET status = '"+ _newStatus + "' WHERE id=" + _payLoad.user_id;
        let updatePanQuery = "UPDATE user_documents SET status = '" + _payLoad.panstatus + "' WHERE id= " + _payLoad.panid + " AND user_id=" + _payLoad.user_id;
        let updateFinanceQuery = "UPDATE user_finance_details SET status = '" + _payLoad.financestatus +" 'WHERE id= " + _payLoad.financeid + " AND user_id=" + _payLoad.user_id;

        db.tx(function (t) {
            console.log("4");
            // `t` and `this` here are the same;
            // this.ctx = transaction config + state context;
            return t.batch([
                t.none(updateuserQuery),
                t.none(updatePanQuery),
                t.none(updateFinanceQuery)
            ]);
        }).then(function (data) {
            _resolve(data);
        }).catch(function (error) {
            _reject(error);
        });


    });

    _getCurrentStatus(payLoad.user_id)
    .then(_setUpdateStatus)
    .then( _updateStatus(newStatus, payLoad))
    .then( values => {
            resolve(values);
        },error => {
            reject(error);
    })
    .catch((error) => reject(error));
});
1

There are 1 best solutions below

2
On BEST ANSWER

You are overcomplicating thing here. First feedback is that you don't need those new Promise wrappers, since pg-promise is already creating promises. You can greatly flatten things here:

function getCurrentStatus(userId) {
  console.log("1");
  let statusQuery = "SELECT status FROM users WHERE id=" + userId;

  return db.one(statusQuery).then(function (data) {               
    console.log("2");
    return data.status;
  });      
}

function getUpdatedStatus(cStatus) 
  console.log('2');

  if (allApproved) {
    if(cStatus == 'nvd_pending'){
      newStatus = 'finance_pending';
    } else if (cStatus == 'finance_pending'){
      newStatus = 'oracle_pending';
    } else if (cStatus == 'oracle_pending'){
      newStatus = 'active';
    } else {
       newStatus = cStatus;
    }
  } else {
    newStatus = 'nvd_pending';
  }
  return newStatus;
}

function updateStatus(newStatus, payLoad) {
    console.log("3");

    let updateuserQuery = "UPDATE users SET status = '"+ newStatus + "' WHERE id=" + payLoad.user_id;
    let updatePanQuery = "UPDATE user_documents SET status = '" + payLoad.panstatus + "' WHERE id= " + payLoad.panid + " AND user_id=" + payLoad.user_id;
    let updateFinanceQuery = "UPDATE user_finance_details SET status = '" + payLoad.financestatus +" 'WHERE id= " + payLoad.financeid + " AND user_id=" + payLoad.user_id;

    return db.tx(function (t) {
        console.log("4");
        // `t` and `this` here are the same;
        // this.ctx = transaction config + state context;
        return t.batch([
            t.none(updateuserQuery),
            t.none(updatePanQuery),
            t.none(updateFinanceQuery)
        ]);
    });
});

function updateCurrentStatus(payLoad) {
  return getCurrentStatus(payLoad.user_id)
    .then(cStatus => getUpdatedStatus(cStatus))
    .then(newStatus => updateStatus(newStatus, payLoad));
}

The specific reason you're seeing 3 out of order is because you're calling it immediately via _updateStatus(newStatus, payLoad) instead of wrapping it in a function (see my suggested code updates above).