0

db クエリを 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));
});
4

1 に答える 1

2

あなたはここで物事を過度に複雑にしています。最初のフィードバックは、既に promise を作成している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)(上記の提案されたコードの更新を参照してください)。

于 2017-01-08T08:10:03.487 に答える