Express+EJS项目中如何在路由调用控制器函数并传数据至视图?
解决Express+EJS项目中控制器数据无法传递到视图的问题
我来帮你分析下问题所在,然后一步步解决:
核心问题分析
你的代码里有两个关键问题导致视图拿不到数据:
- 异步操作处理错误:
banners函数里的数据库查询是异步操作,你直接在回调里return results根本无法把数据传递出去——异步回调的return不会让外部函数返回值,而且你写的var data = results在return之后,根本不会执行。 - 路由调用方式错误:你在路由里把
home.banners这个函数对象直接传给了视图,而没有执行它去获取数据库数据,视图拿到的只是一个函数,不是实际的查询结果。
解决方案步骤
第一步:修改控制器home.js,正确处理异步数据传递
我们把banners改成支持回调(或者Promise,推荐后者)的方式,让它能把异步查询到的数据传递出去:
方式1:使用回调函数
var config = require('../../config/config'); // 假设connection是你已经配置好的数据库连接实例 exports.banners = function(callback) { // 连接数据库 connection.connect(function(err) { if (err) { console.error('数据库连接失败:', err); return callback(err, null); // 把错误传给回调 } console.log('数据库连接成功...'); // 执行查询 connection.query( 'SELECT * FROM banner_management WHERE banner_status ="Active" AND banner_type = "home_page" Limit 0,1', function(err, results) { // 查询完成后关闭连接(如果是单次连接的话,用连接池可以省略这步) connection.end(); if (err) { console.error('Banner查询失败:', err); return callback(err, null); } // 把查询结果通过回调返回 callback(null, results); } ); }); }
方式2:使用Promise(更现代,推荐)
var config = require('../../config/config'); exports.banners = function() { return new Promise((resolve, reject) => { connection.connect(function(err) { if (err) { console.error('数据库连接失败:', err); return reject(err); } console.log('数据库连接成功...'); connection.query( 'SELECT * FROM banner_management WHERE banner_status ="Active" AND banner_type = "home_page" Limit 0,1', function(err, results) { connection.end(); if (err) { console.error('Banner查询失败:', err); return reject(err); } resolve(results); } ); }); }); }
第二步:修改路由文件,正确调用控制器并渲染视图
根据你选择的控制器方式,修改路由代码:
如果用回调方式
// 把require放在路由文件顶部,不要在请求处理函数里重复加载 var home = require('../app/controllers/home'); /* GET home page. */ router.get('/', function(req, res, next) { // 调用banners函数,传入回调处理结果 home.banners(function(err, bannerData) { if (err) { // 把错误交给Express的错误处理中间件 return next(err); } // 拿到数据后再渲染视图 res.render('index', { title: 'Medical Tourism-Arogyata', data: bannerData, baseUrl: 'http://localhost:3000/' }); }); });
如果用Promise方式(推荐用async/await简化代码)
var home = require('../app/controllers/home'); /* GET home page. */ router.get('/', async function(req, res, next) { try { // 等待异步查询完成拿到数据 const bannerData = await home.banners(); // 渲染视图并传递数据 res.render('index', { title: 'Medical Tourism-Arogyata', data: bannerData, baseUrl: 'http://localhost:3000/' }); } catch (err) { // 捕获错误并交给错误中间件 next(err); } });
额外优化建议
- 数据库连接池:每次请求都创建新的数据库连接效率很低,建议改用连接池(比如mysql的
createPool方法),在config里配置好连接池,然后每次从池里获取连接,避免频繁创建/关闭连接。 - 错误处理:在生产环境中不要直接
throw err,最好把错误传递给Express的错误处理中间件统一处理。
内容的提问来源于stack exchange,提问作者Surya prakash Patel
相关产品推荐
相关产品推荐

