Node.js中如何将req参数传入SQL查询函数?
问题分析
你遇到的核心问题是异步操作的处理错误和变量作用域混乱:
- 最初的
getInfo函数是异步执行的,但你同步调用后直接渲染视图,此时查询还没完成,数据根本没拿到;而且函数内部的camInfo是局部变量,外部完全访问不到。 - 尝试
async/await时用法错误——mysqlConf.getConnection是回调式API,不能直接await,必须先包装成Promise才能配合异步语法使用。 - 代码里存在变量名混淆(比如
results未声明就使用、result重复定义)、错误抛出方式错误(throw new err()是无效写法)等细节问题。
解决方案
把MySQL的回调式API包装成Promise,用async/await规范处理异步逻辑,同时将查询函数封装成独立的、接收明确参数的模块。
步骤1:包装MySQL API为Promise
Node.js内置的util.promisify可以快速把回调函数转成Promise:
const util = require('util'); // 把getConnection和query方法转成Promise版本 const getConnection = util.promisify(mysqlConf.getConnection.bind(mysqlConf)); const query = util.promisify((connection, sql, params) => connection.query(sql, params));
步骤2:封装查询函数
不需要传递整个req,直接传需要的product_code更清晰:
// 获取相机基础信息 async function getCameraInfo(productCode) { let connection; try { connection = await getConnection(); // 按product_code查询,结果应该只有一条,直接取rows[0] const rows = await query(connection, 'SELECT * FROM camera_info WHERE product_code = ?', [productCode]); return rows[0] || null; } catch (err) { console.error('获取相机信息失败:', err); throw err; // 抛出错误让上层处理 } finally { if (connection) connection.release(); // 确保数据库连接释放 } } // 获取相机功能列表 async function getCameraFeatures(productCode) { let connection; try { connection = await getConnection(); const rows = await query(connection, 'SELECT * FROM cam_features WHERE product_code = ?', [productCode]); return rows; // 返回所有功能条目 } catch (err) { console.error('获取相机功能失败:', err); throw err; } finally { if (connection) connection.release(); } }
步骤3:修改路由处理逻辑
用async/await等待两个查询完成,再渲染视图:
app.get('/product-page/:product_code', async (req, res) => { try { const productCode = req.params.product_code; // 并行执行两个查询,提升性能 const [cameraInfo, cameraFeatures] = await Promise.all([ getCameraInfo(productCode), getCameraFeatures(productCode) ]); // 如果相机不存在,返回404 if (!cameraInfo) { return res.status(404).send('该相机不存在'); } // 把两个表的数据传给视图 res.render('test-view', { info: cameraInfo, features: cameraFeatures }); } catch (err) { console.error('路由处理失败:', err); res.status(500).send('服务器内部错误'); } });
额外优化点
- 视图里可以直接用
<%= info.xxx %>调用相机基础信息,用<% features.forEach(feature => { %> ... <% }) %>遍历功能列表。 - 避免全局变量污染,所有变量都用
let/const声明。 - 统一错误捕获,防止单个查询失败导致服务器崩溃。
内容的提问来源于stack exchange,提问作者Yenmangu
相关产品推荐
相关产品推荐

