Node.js使用Express如何按顺序发送执行MySQL查询
问题根源
你加async/await不生效的核心原因是:dbController.query是传统回调风格的异步方法,本身不返回Promise对象,而await关键字仅对Promise生效,直接在这类回调方法前加await不会等待异步操作执行完成。
Node.js 执行异步IO操作(比如数据库查询)时,不会阻塞主线程等待结果返回,会直接执行后续的同步代码,等IO操作完成后才会执行传入的回调函数。你代码里的console.log('<---- 2 ---->')是同步代码,所以会先于两个查询的回调执行,才会出现你看到的输出顺序。
实现顺序执行的方案
方案1:Promise包装 + async/await(推荐)
把回调风格的查询方法包装成返回Promise的版本,就可以用async/await实现按顺序等待执行:
// 包装回调方法为Promise版本 const runQuery = (sql) => { return new Promise((resolve, reject) => { dbController.query(sql, (err, result) => { if (err) return reject(err) resolve(result) }) }) } router.post('/', async (req, res) => { try { // 等待第一条查询执行完成 await runQuery("SELECT * FROM users WHERE username = 'myUserName'") console.log('<---- 1 ---->') // 执行中间同步逻辑 console.log('<---- 2 ---->') // 等待第二条查询执行完成 await runQuery("SELECT * FROM users WHERE username = 'myUserName'") console.log('<---- 3 ---->') res.send('ok') } catch (err) { // 统一捕获查询错误 res.status(500).send('server error') } })
如果你用的是mysql2库,官方自带Promise版本的驱动,不需要手动包装,直接引入对应版本即可直接使用await:
// 直接引入mysql2的promise版本 const mysql = require('mysql2/promise') const dbController = mysql.createConnection(/* 数据库配置 */)
方案2:回调嵌套(不推荐)
直接把后续逻辑写到前一个异步操作的回调函数里,也能保证执行顺序,但嵌套层级多了会产生回调地狱问题,可维护性差:
router.post('/', (req, res) => { dbController.query( "SELECT * FROM users WHERE username = 'myUserName'", (err, result) => { if (err) return res.status(500).send('server error') console.log('<---- 1 ---->') // 第一条查询完成后执行中间逻辑 console.log('<---- 2 ---->') // 发起第二条查询 dbController.query( "SELECT * FROM users WHERE username = 'myUserName'", (err, result) => { if (err) return res.status(500).send('server error') console.log('<---- 3 ---->') res.send('ok') } ) } ) })
注意事项
- 不要把
res.send写在所有异步逻辑的外层,否则会出现异步操作还没执行完,响应就已经返回的问题 - 所有数据库操作都需要做错误处理,避免异常时服务崩溃
内容的提问来源于stack exchange,提问作者arrmani88
相关产品推荐
相关产品推荐

