Pug继承父模板迭代列表时报Cannot read property 'length' of undefined
问题原因
这个报错的核心触发原因有两个:
- 异步调用逻辑错误:你调用的
connection.query是异步回调API,回调函数内部的return不会将结果返回给外层的getEntryList函数,外层getEntryList默认返回undefined,你传入Pug模板的list变量实际是undefined,Pug执行each遍历逻辑时需要读取对象的length属性,就触发了对应报错。 - SQL查询字段缺失:你当前的查询语句只查了
name字段,后续构造entry对象时用到的row.id根本不存在,就算异步问题解决后续生成的url也会是错误值。
修复方案
有两种常用修复方式,按需选择即可:
方案1:回调式写法(适配原有回调逻辑)
改造getEntryList函数
function getEntryList(db, callback) { // 补充查询id字段 connection.query(connection.format('SELECT id, name FROM ??', [db]), (err, result, fields) => { if (err || !result) { utils.log(`[MySQL] ${err}`); return callback([]); } const list = []; // result本身是数组,直接遍历即可 result.forEach(row => { const entry = {title: row.name, url: `/${db}/${row.id}`}; list.push(entry); }); callback(list); }); }
改造路由逻辑
app.get('/employees', localSession, (req, res) => { // 在回调中拿到结果后再执行渲染 getEntryList('employees', (list) => { res.render('employees', {title: 'Employees', list: list}); }); });
方案2:async/await写法(更简洁易维护)
首先将callback风格的query方法Promise化,如果使用的是mysql2包可以直接使用内置的Promise API,老版本mysql包可以用Node.js内置的util工具包装:
const util = require('util'); const query = util.promisify(connection.query).bind(connection);
改造getEntryList为异步函数
async function getEntryList(db) { try { const result = await query('SELECT id, name FROM ??', [db]); // 用map简化数组构造逻辑 return result.map(row => ({title: row.name, url: `/${db}/${row.id}`})); } catch (err) { utils.log(`[MySQL] ${err}`); return []; } }
改造路由逻辑
app.get('/employees', localSession, async (req, res) => { const list = await getEntryList('employees'); res.render('employees', {title: 'Employees', list: list}); });
额外优化建议
可以在Pug的遍历逻辑中加兜底逻辑,避免后续异常再次触发报错:
each entry in list || []
内容的提问来源于stack exchange,提问作者KnusperflockeOfDeath
相关产品推荐
相关产品推荐

