Express项目中res.locals在视图层返回undefined如何解决?
问题原因
- 核心原因是中间件的赋值逻辑存在遗漏:只有当用户存在且处于认证状态(
req.session.user和req.session.isAuthenticated同时为真)时,才会给res.locals.isAuth和res.locals.isAdmin赋值。如果用户未登录、会话过期,代码会直接走return next()跳过赋值逻辑,此时这两个变量根本没有被挂载到res.locals上,视图层访问自然返回undefined。 - 附加排查点:确认你挂载这个自定义中间件的位置在所有路由注册之前,如果把中间件放在路由注册之后,请求走到路由逻辑时还没执行赋值操作,也会出现找不到变量的问题。
解决方法
- 给两个变量设置默认值,不管用户是否登录都完成赋值,同时给异步数据库查询添加错误捕获,避免请求挂起,修改中间件代码如下:
app.use(async function(req, res, next) { const user = req.session.user; const isAuth = req.session.isAuthenticated || false; // 先初始化默认值,保证所有场景下变量都存在 res.locals.isAuth = isAuth; res.locals.isAdmin = false; if (!user || !isAuth) { return next(); } try { const userDoc = await User.findOne({_id: user.id}); res.locals.isAdmin = userDoc?.isAdmin || false; console.log(res.locals.isAuth); next(); } catch (err) { next(err); } });
- EJS模板可以直接访问
res.locals挂载的变量,不需要加locals.前缀,简化模板判断逻辑如下:
<% if(isAdmin) { %> <a id='admin' class="mdl-navigation__link log" href="/users/admin">Admin</a> <% } %> <% if (!isAuth) { %> <% console.log(isAuth + 'Hello') %> <a id='sign' class="mdl-navigation__link" href="/users/signup">Signup</a> <a id='login' class="mdl-navigation__link" href="/users/login">Login</a> <% } else { %> <form id="logout-form" action="/users/logout" method="post"> <button id="logout" type="submit">Logout</button> </form> <% } %>
修改完成后无论用户是否登录,两个变量都有明确的布尔值,不会再出现undefined的问题。
内容的提问来源于stack exchange,提问作者Miro
相关产品推荐
相关产品推荐

