如何将NodeJS MySQL查询结果赋值给全局数组变量
问题核心原因
你遇到的问题本质是异步回调的执行时机晚于后续同步代码,加上getItems没有返回可等待的Promise,导致await关键字没有生效,你遍历itemList的时候数据库查询还没返回结果,数组自然是空的。
异步逻辑通俗解释
你现有的理解基本正确,再举个更具象的例子方便你理解:
- 调用
getItems相当于你给外卖商家打电话下单(发起数据库连接+查询请求) - 挂电话之后你不会一直在门口等外卖,会直接做后面的事:遍历数组、调用
anofuncV2,这时候外卖还没送到,itemList是空的 - 等外卖员敲门(数据库返回查询结果,触发query的回调函数),你才会把数据push进
itemList,但这时候你之前的遍历逻辑早就执行完了
现有代码的两处明显错误
getItems是普通函数,没有返回Promise,你使用await等待它完全不会生效,执行完getItems立刻就会运行后续代码,不会等查询回调执行- 你把
con.end()写在connect回调的finally块中,con.query是异步逻辑,还没等查询返回结果,你就已经关闭了数据库连接,部分场景下甚至会直接导致查询失败
适配需求的修改方案
完全保留你需要的全局数组结构,不需要把后续逻辑塞到query回调里:
首先把getItems改造成返回Promise的函数,这样await就能真的等待查询完成、数组赋值结束之后再执行后续逻辑:
var itemList = []; var siteList = []; // 改造为返回Promise的函数 function getItems(){ return new Promise((resolve, reject) => { con.connect(function(err) { if (err) return reject(err); con.query("SELECT DISTINCT ProductURL FROM products;", function (err, result, fields) { // 查询出错直接抛出 if (err) { con.end(); return reject(err); } // 全局数组赋值 for (let i=0; i<result.length; i++){ itemList.push(result[i].ProductURL); } // 查询完成,关闭连接,标记Promise执行完毕 con.end(); resolve(); }); }); }) } async function another_function(item) { // 处理item逻辑,写入siteList } async function anofuncV2(list) { // 处理siteList逻辑 } // 把后续逻辑包在async入口函数中(Node 14.8+支持直接在顶层写await) async function main() { // 等待getItems执行完毕,此时itemList已经有完整数据 await getItems(); // 遍历执行async函数需要等待异步完成,不要用forEach,改用for...of for (const item of itemList) { await another_function(item); } // 等所有another_function执行完成后再调用anofuncV2 await anofuncV2(siteList); } // 启动入口逻辑 main();
额外注意事项
- 你之前用
forEach调用async函数another_function的写法不会等待所有异步执行完成,会直接提前运行anofuncV2,导致siteList为空,建议改为for...of循环逐个await,或者用Promise.all批量等待 - 数据库连接建议使用连接池复用,不要每次查询都新建连接再关闭,性能更高也更稳定
内容的提问来源于stack exchange,提问作者Beanman
相关产品推荐
相关产品推荐

