异步数据库查询方法首次调用返回undefined问题修复咨询
问题原因
你遇到的是Node.js异步IO的典型执行顺序问题:connection.query是异步方法,调用displayCategories后,代码不会等待数据库查询返回结果,会直接执行后续的session.categories判断逻辑。首次点击时,数据库查询回调还没执行,session.categories还没被赋值,所以输出undefined;后续点击时拿到的是上一次查询已经存到session里的旧值。
另外你现有代码还存在一个隐患:你将session声明为全局变量,多用户并发访问时会出现会话数据串扰的问题,建议直接操作req.session,不要单独提取为全局变量。
修复方案
方案1:回调改造(改动最小)
给displayCategories新增回调参数,把后续逻辑放到回调中执行,确保数据库查询完成后再判断session值:
// 改造displayCategories,新增回调参数 function displayCategories(req, res, callback) { const query = `SELECT DISTINCT name FROM product_category;`; connection.query(query, function (err, rows) { if (err) { console.log(err); res.render("home"); throw err; } else { // 直接操作req.session,不要用全局session req.session.categories = rows[0]; callback(); } }); } // 改造路由逻辑,把session判断放到回调里 router.post('/categories', function (req, res) { displayCategories(req, res, function() { if (req.session.categories === undefined) { console.log("categories is undefined"); } else { console.log("categories is defined"); console.log(req.session.categories); } // 你的响应逻辑也需要放到这里执行,比如res.render、res.send等 }); })
方案2:async/await改造(更易维护)
用Node.js内置的util.promisify把数据库查询转成Promise形式,用async/await控制执行顺序,代码可读性更高:
const util = require('util'); // 将callback形式的query转成Promise形式 const queryAsync = util.promisify(connection.query).bind(connection); async function displayCategories(req, res) { try { const rows = await queryAsync(`SELECT DISTINCT name FROM product_category;`); req.session.categories = rows[0]; } catch (err) { console.log(err); res.render("home"); throw err; } } router.post('/categories', async function (req, res) { // 等待数据库查询完成 await displayCategories(req, res); if (req.session.categories === undefined) { console.log("categories is undefined"); } else { console.log("categories is defined"); console.log(req.session.categories); } })
内容的提问来源于stack exchange,提问作者bob_jones
相关产品推荐
相关产品推荐

