Node.js中Promise执行SQL语句顺序混乱,求正确顺序执行方案
Node.js Promise 实现SQL语句顺序执行问题
我正在学习Node.js与Promise,希望代码中的SQL语句能够顺序执行(一条执行完成后再执行下一条),但当前的Promise实现存在问题,终端输出显示SQL语句的执行顺序混乱(比如“done with three”先于“done with two”输出)。以下是我的代码和输出,求指导如何正确实现顺序执行:
其中一条SQL语句的Promise封装
var selectbotagentstoadd = new Promise((resolve, reject) => { var sql = 'SELECT tbltestbotagentstoadd.AgentID FROM tbltestbotagentstoadd WHERE tbltestbotagentstoadd.IDNumber=? AND tbltestbotagentstoadd.MSISDN=?;' DB.query(sql, [agentidpassnum, agentnumber], function(err, results) { if (err) { return reject(err); }; return resolve(results); }); })
Promise调用语句
await insertbotagentstoadd.then(() => { console.log("done with one"); }) .then(() => { selectbotagentstoadd.then((results) => { AgenttoaddIDStore=[]; results.forEach(agent => { AgenttoaddIDStore.push({ AgentID:agent.AgentID }); ctx.session.tempAgentID=agent.AgentID }); console.log("agent ID: "+ctx.session.tempAgentID); console.log("done with two"); })}) .then((results) => {insertcctblricaagents console.log("done with three"); }) .then((results) => {selectcctblricaagents.then((result) => { console.log(result); AgentnewIDStore=[]; result.forEach(agent => { AgentnewIDStore.push({ AgentID:agent.AgentID }) ctx.session.AgentID=agent.AgentID }) console.log("cctblricaagents agent ID: "+ ctx.session.AgentID); console.log("done with four"); })}) .then(insertcctblricaagentsnum.then((result) => { console.log("done with five"); })) .then(selectcctblricaagentsnum.then((result) => { console.log(result) AgentIDStore=[]; result.forEach(agent => { AgentIDStore.push({ AgentID:agent.AgentID, MainNumber:agent.MainNumber, }) ctx.session.AgentID=agent.AgentID ctx.session.agentnumber=agent.MainNumber }) console.log("cctblricaagentsnum agent ID: "+ ctx.session.AgentID); console.log("done with six"); })) .then(insertcctblintblbotagents.then((result) => { console.log("done with seven"); }));
终端输出结果
Agent number: 27815567777 done with one done with three agent ID: 89 done with two [] cctblricaagents agent ID: null done with four
问题根源
你的代码存在两个核心问题导致顺序混乱:
.then()回调中调用内部Promise但未返回,导致当前回调结束后直接进入下一个.then(),不等待内部Promise完成。比如第二个.then()里执行selectbotagentstoadd.then()但没返回,第三个.then()直接执行,所以"done with three"先出现。- 错误地将Promise的执行结果(而非回调函数)传给
.then(),比如then(insertcctblricaagentsnum.then(...)),这种写法会让该Promise立即执行,不受链式流程控制。
正确实现方式
方式1:用async/await简化(推荐)
既然已经用到await,直接用顺序写法更直观,完全避免链式嵌套:
// 第一步:执行insertbotagentstoadd await insertbotagentstoadd; console.log("done with one"); // 第二步:执行select并处理结果 const selectResults = await selectbotagentstoadd; AgenttoaddIDStore = []; selectResults.forEach(agent => { AgenttoaddIDStore.push({ AgentID: agent.AgentID }); ctx.session.tempAgentID = agent.AgentID; }); console.log("agent ID: " + ctx.session.tempAgentID); console.log("done with two"); // 第三步:执行insertcctblricaagents await insertcctblricaagents; console.log("done with three"); // 第四步:执行selectcctblricaagents并处理结果 const ricaAgentResults = await selectcctblricaagents; console.log(ricaAgentResults); AgentnewIDStore = []; ricaAgentResults.forEach(agent => { AgentnewIDStore.push({ AgentID: agent.AgentID }); ctx.session.AgentID = agent.AgentID; }); console.log("cctblricaagents agent ID: " + ctx.session.AgentID); console.log("done with four"); // 第五步:执行insertcctblricaagentsnum await insertcctblricaagentsnum; console.log("done with five"); // 第六步:执行selectcctblricaagentsnum并处理结果 const numResults = await selectcctblricaagentsnum; console.log(numResults); AgentIDStore = []; numResults.forEach(agent => { AgentIDStore.push({ AgentID: agent.AgentID, MainNumber: agent.MainNumber, }); ctx.session.AgentID = agent.AgentID; ctx.session.agentnumber = agent.MainNumber; }); console.log("cctblricaagentsnum agent ID: " + ctx.session.AgentID); console.log("done with six"); // 第七步:执行insertcctblintblbotagents await insertcctblintblbotagents; console.log("done with seven");
方式2:修复原有的.then()链式调用
如果坚持用链式写法,必须确保每个.then()的回调返回要等待的Promise,让链式流程同步:
await insertbotagentstoadd .then(() => { console.log("done with one"); }) // 返回select的Promise,让链式等待它完成 .then(() => { return selectbotagentstoadd.then((results) => { AgenttoaddIDStore = []; results.forEach(agent => { AgenttoaddIDStore.push({ AgentID: agent.AgentID }); ctx.session.tempAgentID = agent.AgentID; }); console.log("agent ID: " + ctx.session.tempAgentID); console.log("done with two"); }); }) .then(() => { // 返回insert的Promise return insertcctblricaagents.then(() => { console.log("done with three"); }); }) .then(() => { return selectcctblricaagents.then((result) => { console.log(result); AgentnewIDStore = []; result.forEach(agent => { AgentnewIDStore.push({ AgentID: agent.AgentID }); ctx.session.AgentID = agent.AgentID; }); console.log("cctblricaagents agent ID: " + ctx.session.AgentID); console.log("done with four"); }); }) .then(() => { return insertcctblricaagentsnum.then(() => { console.log("done with five"); }); }) .then(() => { return selectcctblricaagentsnum.then((result) => { console.log(result); AgentIDStore = []; result.forEach(agent => { AgentIDStore.push({ AgentID: agent.AgentID, MainNumber: agent.MainNumber, }); ctx.session.AgentID = agent.AgentID; ctx.session.agentnumber = agent.MainNumber; }); console.log("cctblricaagentsnum agent ID: " + ctx.session.AgentID); console.log("done with six"); }); }) .then(() => { return insertcctblintblbotagents.then(() => { console.log("done with seven"); }); });
关键注意事项
- 所有需要等待的异步SQL操作,必须通过
await或者在.then()中返回对应的Promise,才能纳入顺序执行的流程。 - 禁止在
.then()中嵌套Promise却不返回,这会导致内部异步操作脱离控制,打乱执行顺序。
内容的提问来源于stack exchange,提问作者sb_thedev
相关产品推荐
相关产品推荐

