res.locals无法更新始终显示旧值,技术问题求助
res.locals.currentUser with Passport.js 我之前也踩过这个一模一样的坑!这种登录切换用户后,res.locals.currentUser却一直停留在旧值的情况,大多是中间件顺序、用户反序列化逻辑或者缓存机制出了问题,咱们一步步来排查解决:
先检查中间件执行顺序,这是最常见的诱因!
Passport的session功能依赖Express的session中间件,而且你设置res.locals.currentUser的全局中间件,必须放在Passport初始化之后。如果顺序搞反了,req.user还没被Passport更新,locals自然拿的是旧数据。正确的顺序应该是这样:// 1. 先初始化Express Session app.use(session({ secret: 'your-own-secret-key', resave: false, saveUninitialized: false, // 若使用Redis等存储,需在此配置对应store })); // 2. 初始化Passport及其session支持 app.use(passport.initialize()); app.use(passport.session()); // 3. 最后设置全局res.locals app.use((req, res, next) => { res.locals.currentUser = req.user; next(); });要是你把
res.locals的中间件放在Passport之前,每次请求都会先把旧的req.user(甚至是undefined)赋值给locals,后面Passport更新了req.user也无法覆盖。确认
passport.deserializeUser每次都拉取最新用户数据
很多开发者会在这里偷懒用缓存,或者没有正确从数据库重新查询用户,导致用户切换/信息更新后,反序列化出来的还是旧数据。一定要确保每次反序列化都从数据库获取最新记录:passport.deserializeUser(async (userId, done) => { try { // 必须每次查询数据库,不能用内存缓存的用户对象 const latestUser = await User.findById(userId); done(null, latestUser); } catch (err) { done(err); } });要是你之前在这里用了全局变量或缓存存储用户,切换用户后肯定会拿到旧数据。
排查浏览器缓存干扰
有时候后端其实已经更新了res.locals.currentUser,但浏览器缓存了之前的页面,导致你视觉上觉得没变化。可以给动态页面加上禁用缓存的响应头:app.use((req, res, next) => { // 禁止浏览器缓存动态内容 res.set('Cache-Control', 'no-cache, no-store, must-revalidate'); res.set('Pragma', 'no-cache'); res.set('Expires', '0'); next(); });这个中间件可以放在全局中间件最前面,确保所有响应都带上这些头。
检查是否有路由手动覆盖了
res.locals.currentUser
看看你的路由里有没有手动给res.locals.currentUser赋值的代码,比如有些开发者会在特定路由里硬编码或用旧数据赋值,导致全局中间件的设置被覆盖。如果有,删掉这些手动赋值,统一用全局中间件处理。
按这几步排查下来,应该就能解决res.locals.currentUser不更新的问题了!
内容的提问来源于stack exchange,提问作者Chola Tech

