2017-05-16 4 views
1

mysqlデータベースを2回クエリしていますが、2回目、それぞれの結果に対して複数回クエリを実行しようとしていますが、NodeJSは毎回結果を待っているforeachループの中でpromise-mysqlクエリを実行しています

admin.get('/', function (req, res) { 
     mysqlQ("SELECT I.ID as ID, C.ID AS CID, I.PD AS PostDate, C.Name AS CatName, U.UserName AS UserName, I.Title AS Title, I.Post AS PostData FROM categories AS C JOIN INAT AS I ON C.ID = I.Category JOIN Users AS U on U.ID = I.User").then(function (INAT) { 
     INAT.forEach(function (team) { 
      team.time = moment(team.PostDate).format("DD-MM-YYYY HH:mm:ss"); 
      team.TS = moment(team.time, "DD-MM-YYYY HH:mm:ss").fromNow(); 
      mysqlQ("SELECT I.ID AS InatID, J.Name AS JobTitle, C.Name AS Category FROM `Jobs` AS J JOIN Jobs2INAT AS J2I ON J.ID = J2I.JobsID JOIN INAT AS I ON I.ID = J2I.INATID JOIN categories AS C on C.ID = J.Categories WHERE I.ID = " + team.ID).then(function (jobs) { 
        team.jobs = jobs; 
       }); 
     }); 
     var context = { 
      INAT: INAT 
     }; 
     var homeTemplate = pug.compileFile(__dirname + '/templates/home.pug'); 
     var html = homeTemplate(context); 
     res.send(html); 
    }); 
}) 
+0

可能な複製を終了することを忘れないでください非同期呼び出しからの応答?](http://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) - このコードはNodeJSであり、AJAXではありません同じ原則が適用されます –

答えて

1

あなたが実際に一度すべてあなたの二次照会はwhen.all()またはbluebird.all(またはそれに相当*.map)を有する第二約束を構築し、戻ってきた解決されます第二約束を作成する必要が

ます。また、変更しようとしていますあなたのINATオブジェクトのエントリを更新する前に解決することを約束するためにあなたの二分の二を待つ必要がありますので、INATを更新し、最終結果を送信してください。

var Promise = require('bluebird'); // or use any other Promise library 

admin.get('/', function (req, res) { 
    mysqlQ("SELECT I.ID as ID, C.ID AS CID, I.PD AS PostDate, C.Name AS CatName, U.UserName AS UserName, I.Title AS Title, I.Post AS PostData FROM categories AS C JOIN INAT AS I ON C.ID = I.Category JOIN Users AS U on U.ID = I.User") 
     .then(function (INAT) { 
      var promiseArray = []; 
      promiseArray.push(Promise.resolve(INAT)); 
       // For each INAT entry create a new Promise that will resolve with your job 
       INAT.forEach(function (team) { 
        team.time = moment(team.PostDate).format("DD-MM-YYYY HH:mm:ss"); 
        team.TS = moment(team.time, "DD-MM-YYYY HH:mm:ss").fromNow(); 
        promiseArray.push(
         mysqlQ("SELECT I.ID AS InatID, J.Name AS JobTitle, C.Name AS Category FROM `Jobs` AS J JOIN Jobs2INAT AS J2I ON J.ID = J2I.JobsID JOIN INAT AS I ON I.ID = J2I.INATID JOIN categories AS C on C.ID = J.Categories WHERE I.ID = " + team.ID) 
        ); 
       }); 

      return Promise.all(promiseArray); 
     }).then(function(results) { 
      // Add the looked-up jobs to INAT 
      var [INAT, ...jobs] = results; 
      INAT.forEach(function(team, i) { 
       team.jobs = jobs[i]; 
      }) 

      // Send your answer 
      var context = { 
         INAT: INAT 
      }; 
      var homeTemplate = pug.compileFile(__dirname + '/templates/home.pug'); 
      var html = homeTemplate(context); 
      return res.send(html); 
     }).catch(function(err) { 
      // do some error handling 
      return res.send("Unable to process/=> err = "+err); 
     }) 
    }) 

PSを動作するはずです。このような多くのことを行うための方法が、何かがあります:私はどのように返すか、[すべてのあなたのreturnステートメントを使用して.then(function() {})

+0

ありがとう、本当に私が約束を理解するのを助けてくれた! –

+0

@ bertie.io Borisがロールバックしたいと思うなら、私が編集レビューのキューで間違って辞退してしまったので、私はあなたの編集を適用しました。 –

0

この問題は、2番目の約束が解決する前に変数を割り当てることを試みていることです。

2つの約束を返すようにするために、あなたが待っている場合は、最後の約束は

admin.get('/', function (req, res) { 
    mysqlQ("SELECT I.ID as ID, C.ID AS CID, I.PD AS PostDate, C.Name AS CatName, U.UserName AS UserName, I.Title AS Title, I.Post AS PostData FROM categories AS C JOIN INAT AS I ON C.ID = I.Category JOIN Users AS U on U.ID = I.User").then(function (INAT) { 
    INAT.forEach(function (team) { 
     team.time = moment(team.PostDate).format("DD-MM-YYYY HH:mm:ss"); 
     team.TS = moment(team.time, "DD-MM-YYYY HH:mm:ss").fromNow(); 
     mysqlQ("SELECT I.ID AS InatID, J.Name AS JobTitle, C.Name AS Category FROM `Jobs` AS J JOIN Jobs2INAT AS J2I ON J.ID = J2I.JobsID JOIN INAT AS I ON I.ID = J2I.INATID JOIN categories AS C on C.ID = J.Categories WHERE I.ID = " + team.ID).then(function (jobs) { 
       team.jobs = jobs; 

       // *************<<<<<<<<<<< 
       // Any code that needs to wait for the second mysqlQ query needs to go here 
       // *************<<<<<<<<<<< 
       var context = { 
        INAT: INAT 
       }; 
       var homeTemplate = pug.compileFile(__dirname + '/templates/home.pug'); 
       var html = homeTemplate(context); 


      }); 
    }); 
    res.send(html); 
    // var context = { 
    //  INAT: INAT 
    // }; 
    // var homeTemplate = pug.compileFile(__dirname + '/templates/home.pug'); 
    // var html = homeTemplate(context); 
    // res.send(html); 
}); 

}を解決した後、最終的にアクションを実行する必要があります)上記のような

何かがうまくいく、まだ少しもののおそらくJS開発者が好んでいる "コールバック/約束地獄"のために恐怖を覚えています。

+0

これは、毎回foreachループがブラウザにリクエストを送信するたびにExpressリクエストが送信される原因になります –

+0

@ bertie.ioあなたが正しいです!それを修正するために私のポストを編集しました。ヘッダーを2回送信することはできません。 – taskforce

関連する問題