NodeJS在foreach循环中运行一个promise-mysql查询,每次都等待结果

我想查询一个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); }); }) 

您实际上需要创build第二个承诺,一旦您的所有辅助查询都返回,就会解决这个问题,然后使用when.all()bluebird.all (或其等价的*.map )构build第二个承诺。

您也在尝试修改INAT对象中的条目,但是这样做也需要等待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() {})

你的问题是这样的,你试图在第二个承诺解决之前分配你的variables。

如果您等待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开发者喜欢的“callback/承诺地狱”,可能会被折磨。