2017-01-08 4 views
0

私のdbクエリを私の約束ベース関数と同期させるにはどうすればいいですか?私のコードでは、3つの異なる関数の中で3つのdb演算を実行しています。これは、滝モデルのように順番に実行する必要があります。関数はウォーターフォールモデルで実行されていますが、これらの関数内の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)); 
}); 
+3

「同期」と言うとき、「シリアルに」という意味ですか? '.then()'と一緒に連鎖するだけでいいです。約束事を同期して実行することはできません。 – Jacob

+0

はい、私は鎖を意味します。この現在の例では、現在のステータスに基づいてユーザーの現在のステータスを取得することになり、ユーザーは新しいステータスを取得し、ステータスは更新されます。 問題はdb部分です。それは事を非同期にし、私の約束関数はdb結果を待たずに戻ります。 – pkd

+1

話題にはなりませんが重要ですが、パラメータ化されたクエリを使用する代わりに、文字列連結によってSQLを構築しています。したがって、コードがSQLインジェクション攻撃に対して脆弱になる可能性があります。私はPostgreSQLのエキスパートではありませんが、この問題を解決するには[PREPARE'dステートメント](https://www.postgresql.org/docs/9.2/static/sql-prepare.html)をご覧ください。 – stakx

答えて

2

pg-promiseはすでに約束をしているので、最初にフィードバックすると、new 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)); 
} 

あなたが(私の提案上記のコードは更新を参照)関数でラップするのではなく_updateStatus(newStatus, payLoad)を経由して、すぐにそれを呼び出しているので、あなたは順不同で3を見ている具体的な理由があります。

+0

Thnx Jacob。 あなたのソリューションは私の問題を解決しました。以前は私は非同期モジュールを使用していましたが、今はそれぞれのサービスコードベースが最大4MBのサイズと非同期の依存モジュールを必要とするマイクロサービスベースのソリューションを構築するために取り組んでいます。私は約束ベースのアーキテクチャのためのより良い指針を得ることができる場所を私に提案することができます。 – pkd

+0

ありがとうございました;良い答え;)約束をよく理解していない開発者に 'pg-promise'を適切に使用して教えてくれて、疲れていました。 –

関連する問題