Node.js中如何从JavaScript函数获取MySQL查询结果?
解决Node.js中MySQL查询结果无法存入全局数组的问题
这个问题其实是Node.js异步编程的典型坑——你遇到的不是作用域问题,而是异步操作的时序问题!
问题根源
connection.query()是一个异步方法:当你调用get_members()时,JS会立刻继续执行后面的console.log(db_members),但这时候MySQL查询还在后台运行,回调函数还没执行,所以你的全局数组还是空的。而回调里的console.log(db_members)能正常输出,是因为那时候查询已经完成,数据已经被push进去了。
正确的实现方式
不推荐用全局变量来存异步获取的数据(很容易踩时序坑),更合理的做法是让函数把结果“交出来”,下面给两种常用方案:
方案1:使用回调函数(传统方式)
修改get_members,让它接受一个回调参数,查询完成后通过回调返回结果:
const mysql = require('mysql'); const connection = mysql.createConnection({ host : 'xxxx', port : '3306', user : 'xxxx', password : 'xxxx', database : 'xxxx' }); function get_members(callback){ connection.query("SELECT * FROM users", (err, result, fields)=>{ if (err) return callback(err); // 出错时把错误传给回调 // 直接提取用户名并返回 const usernames = result.map(row => row.username); callback(null, usernames); }); } // 调用函数时,在回调里处理结果 get_members((err, db_members) => { if (err) throw err; console.log(db_members); // 这里能正常拿到数据 // 所有需要用到这个数据的逻辑都要写在回调里 });
方案2:使用async/await(推荐,更易读)
Node.js的util.promisify可以把回调式的API转换成Promise,这样就能用async/await来写同步风格的异步代码:
const mysql = require('mysql'); const util = require('util'); const connection = mysql.createConnection({ host : 'xxxx', port : '3306', user : 'xxxx', password : 'xxxx', database : 'xxxx' }); // 把query方法转换成返回Promise的版本 connection.query = util.promisify(connection.query); async function get_members(){ try { const result = await connection.query("SELECT * FROM users"); return result.map(row => row.username); } catch (err) { throw err; // 抛出错误让调用者处理 } } // 调用async函数需要用await,所以要放在async函数里 (async () => { const db_members = await get_members(); console.log(db_members); // 后续业务逻辑写在这里 })();
关键提示
- 永远不要假设异步操作会在你需要数据的时候刚好完成,必须在异步操作的“完成回调”或者
await之后处理数据。 - 尽量避免用全局变量传递异步数据,而是通过函数返回值或者回调来传递,代码会更清晰,也不容易出bug。
内容的提问来源于stack exchange,提问作者user2033139
相关产品推荐
相关产品推荐

