Node.js中使用Promise操作MySQL后变量lesEquipes为何为空?
为什么第三个then里的lesEquipes变量为空?
这个问题我之前也碰到过,核心原因是异步操作的执行顺序没处理对,咱们一步步拆解:
问题根源
你在第一个then的循环里,对每个团队发起了查询成员的database.query请求,但这个请求是异步的——JavaScript不会等着它执行完再走下一次循环,而是会直接把所有异步请求“扔出去”,然后立刻执行循环后面的console.log,接着直接进入第三个then。这时候所有查询成员的请求还在后台跑,lesEquipes自然还没被填充,所以打印出来是空的。
解决方案:用Promise.all等待所有异步请求完成
我们需要把每个团队的成员查询操作包装成Promise,收集到一个数组里,然后用Promise.all等待所有Promise都执行完成后,再继续后续逻辑。同时还要修复一个严重的问题:你的SQL语句用了字符串拼接,存在SQL注入风险,必须改成参数化查询。
修改后的代码核心部分如下:
app.post('/visu',function(req,res){ if((req.body.email == "john@gmail.com") && (req.body.mdp == "password")){ var leUser = "administrateur"; let lesEquipes = []; let test = 'Toto'; database.query("select * from equipe order by id") .then( result => { // 收集所有团队成员查询的Promise const memberQueries = result.map(equipe => { const idEquipe = equipe.id; // 使用参数化查询避免SQL注入 return database.query("select * from participant where equipe = ?", [idEquipe]) .then(result2 => { // 把团队和成员组合起来,存入lesEquipes lesEquipes[idEquipe] = [equipe, result2]; console.log("Membres de l'équipe : " + equipe.nomEquipe); console.log("COURANTE 2 "+ JSON.stringify([equipe, result2])); }); }); // 等待所有成员查询完成后,再进入下一个then return Promise.all(memberQueries); }) .then(() =>{ console.log("Contenu "+ JSON.stringify(test)); console.log("Contenu "+ JSON.stringify(lesEquipes)); res.render('visuEquipes.ejs', { user:leUser, equipes : lesEquipes}); }) .catch((err) => { console.log(err); database.close(); }); } });
关键修改点说明
- 用
Array.map替代for循环:把每个团队的处理逻辑转换成Promise,存入memberQueries数组。 - 参数化查询:把
"select * from participant where equipe = " + result[i].id改成"select * from participant where equipe = ?", [idEquipe],既安全又符合MySQL驱动的最佳实践。 Promise.all等待所有异步操作:只有当所有成员查询都完成后,才会进入下一个then,这时候lesEquipes已经被完全填充了。
另外还有个小细节:你原来代码里在内部then里重新声明了let test = 'AUTRE CHOSE';,这会覆盖外部的test变量,但因为是异步执行,外部的console.log还是会先打印原来的Toto,这个如果不是你想要的逻辑,也可以调整一下。
内容的提问来源于stack exchange,提问作者Eric D.
相关产品推荐
相关产品推荐

