Express app.use设置res.locals无效 res.render传参正常
问题成因
- 核心原因是Pug模板的作用域查找规则限制:以
-开头的无缓冲原生JS代码块中,标识符默认优先查找当前模板作用域内声明的变量、res.render方法显式传入的上下文属性,挂载在app.locals、res.locals上的属性默认挂载在模板内部的locals对象上,旧版本Pug与Express的集成逻辑不会自动把locals上的属性解构到模板的顶层执行作用域,直接调用flatSitemap()时会拿到undefined,触发"flatSitemap is not a function"错误。 - 额外触发因素:测试代码中同一个路由回调写了两次
res.render,HTTP响应流是一次性的,第一次调用render后响应就会开始发送,第二次调用会向已处于发送/关闭状态的流写入内容,引发上下文错乱,也可能触发同类错误。 - 冗余赋值逻辑的影响:同时在全局中间件给
res.locals.flatSitemap赋值、给app.locals.flatSitemap赋值,若后续有其他中间件修改了res.locals上的同名属性为非函数值,也会导致调用失败。
解决方案
- 方案1(最稳妥,无版本兼容问题):在Pug模板的JS代码块中显式从
locals对象读取方法,不依赖自动变量提升:
- var paths = locals.flatSitemap(sitemap);
- 方案2:清理冗余配置,全局通用工具函数直接挂载到
app.locals即可,不需要在每个请求的中间件中重复给res.locals赋值,同时删除路由中重复的res.render调用,单个路由仅保留一次响应逻辑:
// 删除冗余的中间件赋值逻辑 /* app.use(function (req, res, next) { res.locals.flatSitemap = fsm.flatSitemap; next(); }); */ app.locals.flatSitemap = fsm.flatSitemap; app.get('/', function(req, res) { // 仅保留一次render调用,无需重复传入已挂载到全局locals的属性 res.render('./index'); });
- 方案3:若仍存在问题,可在渲染前打印日志校验值类型,确认没有其他中间件覆盖同名属性:
app.get('/', function(req, res) { // 正常情况此处两个输出都应该为 function console.log('flatSitemap类型:', typeof app.locals.flatSitemap, typeof res.locals.flatSitemap); res.render('./index'); });
内容的提问来源于stack exchange,提问作者ImTalkingCode
相关产品推荐
相关产品推荐

