connect-flash无法将success_msg传递至res.locals问题求助
问题
尝试使用connect-flash设置闪存消息,但消息无法正常传递,res.locals.success_msg始终未被正确赋值。手动执行res.locals.success_msg = 'great';时页面可正常显示消息,但通过connect-flash方式失效。已安装所有依赖包,相关代码及日志如下:
Express 后端代码
const express = require('express'); const bodyParser = require('body-parser'); const path = require('path'); require('dotenv').config(); // Load environment variables const app = express(); const PORT = process.env.PORT || 3000; // Use the port from .env or default to 3000 const session = require('express-session'); const mongoose = require('mongoose'); const MongoStore = require('connect-mongo'); const mongoURI = process.env.MONGO_URI || 'mongodb://localhost:27017/sessionDB'; const flash = require('connect-flash'); // Connect to MongoDB with mongoose mongoose.connect(mongoURI) .then(() => { console.log('Connected to MongoDB'); }) .catch((err) => { console.error('MongoDB connection error:', err); }); // Define middleware app.use(bodyParser.urlencoded({ extended: true })); app.set('view engine', 'ejs'); app.use(express.static(path.join(__dirname, 'public'))); app.use(bodyParser.json()); app.use(express.json()); app.use(flash()); // Session setup - generates a session cookie to use for logged in user app.use( session({ secret: process.env.COOKIE_SECRET || "er@(-_45rgD", resave: false, saveUninitialized: true, cookie: { secure: false, maxAge : 5 * 60 * 1000, sameSite: 'Strict' }, store: MongoStore.create({ mongoUrl: mongoURI, collectionName: 'sessions', ttl: 14 * 24 * 60 * 60, }), }) ); // Middleware to pass flash messages to views app.use((req, res, next) => { console.log('flash sucess before setting locals:', req.flash('success_msg')); // Logs flash messages before setting locals console.log('flash error before setting locals:', req.flash('error_msg')); // Logs flash messages before setting locals res.locals.success_msg = req.flash('error_msg')[0] || ''; res.locals.error_msg = req.flash('error_msg')[0]|| ''; console.log('locals after setting:', res.locals); // Logs locals object after setting flash messages next(); }); // Define routes app.get('/flashsuccess', async (req, res) => { console.log('flashsuccess'); req.flash('success_msg', 'This is a success message'); res.redirect('/'); }); app.get('/flasherror', async (req, res) => { console.log('flasherror'); req.flash('error_msg', 'This is an error message'); res.redirect('/'); }); app.get('/', (req, res) => { console.log('Flash messages:', req.flash()); // Log flash messages directly console.log('Locals:', res.locals); // Log locals directly res.render('index'); // Render with flash messages }); // Start the server app.listen(PORT, () => { console.log(`Server running at http://localhost:${PORT}`); });
EJS 模板代码(index.ejs)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>MongoDB</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"> </head> <body> <div class="container mt-5"> <!-- Success Flash Message --> <% if (success_msg) { %> <div class="alert alert-success alert-dismissible fade show" role="alert"> <%= success_msg %> <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button> </div> <% } %> <!-- Error Flash Message --> <% if (error_msg) { %> <div class="alert alert-danger alert-dismissible fade show" role="alert"> <%= error_msg %> <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button> </div> <% } %> <a href="flashsuccess">set flash success message</a><br> <a href="flasherror">set flash error message</a><br> </div> </body> </html>
控制台输出日志
flashsuccess flash sucess before setting locals: [ 'This is a success message' ] flash error before setting locals: [] locals after setting: [Object: null prototype] { success_msg: '', error_msg: '' } Flash messages: {} Locals: [Object: null prototype] { success_msg: '', error_msg: '' }
问题定位与解决
核心错误点
- 中间件顺序错误:
connect-flash依赖express-session,必须在session中间件之后加载,否则无法读取会话中的闪存消息。 - 闪存消息读取逻辑错误:
req.flash()调用会一次性清空对应类型的消息队列,日志中提前调用req.flash('success_msg')后,后续再调用就拿不到值。- 赋值
res.locals.success_msg时错误使用req.flash('error_msg'),未对应正确的消息类型。
- 根路由多余调用:
req.flash()不带参数会取出所有消息并清空,导致模板无法获取值。
修正后的代码
调整中间件顺序并修复闪存逻辑
// ... 其他代码不变 // 先加载session中间件,再加载flash app.use( session({ secret: process.env.COOKIE_SECRET || "er@(-_45rgD", resave: false, saveUninitialized: true, cookie: { secure: false, maxAge : 5 * 60 * 1000, sameSite: 'Strict' }, store: MongoStore.create({ mongoUrl: mongoURI, collectionName: 'sessions', ttl: 14 * 24 * 60 * 60, }), }) ); app.use(flash()); // 移到session中间件之后 // Middleware to pass flash messages to views app.use((req, res, next) => { // 先将消息存入变量,避免重复调用req.flash()导致清空 const successMsg = req.flash('success_msg'); const errorMsg = req.flash('error_msg'); console.log('flash success messages:', successMsg); console.log('flash error messages:', errorMsg); res.locals.success_msg = successMsg[0] || ''; res.locals.error_msg = errorMsg[0] || ''; console.log('locals after setting:', res.locals); next(); }); // ... 其他代码不变 // 根路由移除多余的req.flash()调用 app.get('/', (req, res) => { console.log('Locals:', res.locals); res.render('index'); });
验证效果
修正后,访问/flashsuccess跳转回首页会正常显示成功提示,访问/flasherror则显示错误提示,控制台日志中res.locals会正确赋值对应消息内容。
内容的提问来源于stack exchange,提问作者Patrik Horemans
相关产品推荐
相关产品推荐

