使我的数据库查询与基于promise的函数同步

时间:2017-01-08 07:28:45

标签: node.js asynchronous promise bluebird pg-promise

如何使我的数据库查询与我的promise基函数同步?在我的代码中,我在3个不同的函数中运行3个db操作,这些函数需要按顺序运行,比如瀑布模型。这些函数在瀑布模型中运行,但这些函数中的db查询在异步中工作。我需要在同步中的那些函数中运行db查询。

在这个例子中,我期待在控制台中:

1
2
3
4

但我得到了

1
3
2
4

代码:

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 个答案:

答案 0 :(得分:2)

你在这里过于复杂。第一反馈是,您不需要那些new Promise包装器,因为pg-promise已经在创建承诺。你可以在这里大大扁平化:

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));
}

您看到3无序的具体原因是因为您通过_updateStatus(newStatus, payLoad)立即调用它而不是将其包装在一个函数中(请参阅上面建议的代码更新) )。