Node.js+Express+EJS项目yearData未定义错误排查求助
问题:EJS中
yearData未定义错误排查 基于Node.js(Express.js)、MySQL和EJS搭建网站,尝试用d3.js实现图表展示,访问页面时触发ReferenceError: yearData is not defined,控制台无法输出yd日志,怀疑变量传递环节出错。
相关代码片段
mainpage.ejs脚本部分
<script src="https://d3js.org/d3.v6.min.js"></script> <script> const yearData = <%- JSON.stringify(yearData) %>; const yearChartWidth = 600; const yearChartHeight = 400; const margin = { top: 20, right: 20, bottom: 30, left: 40 }; const svg = d3.select('#yearChart') .append('svg') .attr('width', yearChartWidth + margin.left + margin.right) .attr('height', yearChartHeight + margin.top + margin.bottom) .append('g') .attr('transform', `translate(${margin.left}, ${margin.top})`); const xScale = d3.scaleBand() .domain(yearData.map(d => d.year)) .range([0, yearChartWidth]) .padding(0.1); const yScale = d3.scaleLinear() .domain([0, d3.max(yearData, d => d.count)]) .range([yearChartHeight, 0]); svg.selectAll('.bar') .data(yearData) .enter() .append('rect') .attr('class', 'bar') .attr('x', d => xScale(d.year)) .attr('y', d => yScale(d.count)) .attr('width', xScale.bandwidth()) .attr('height', d => yearChartHeight - yScale(d.count)) .attr('fill', 'steelblue'); svg.append('g') .attr('transform', `translate(0, ${yearChartHeight})`) .call(d3.axisBottom(xScale)); svg.append('g') .call(d3.axisLeft(yScale)); </script>
server.js路由处理代码
app.get('/', (req, res) => { const yearQuery = `SELECT release_year, COUNT(*) AS count FROM movies GROUP BY release_year`; let yd = []; connection.query(yearQuery, (err, yearResults) => { if (err) { console.error('Error fetching year data:', err); return res.status(500).send('Internal Server Error'); } yd = yearResults.map(row => ({ year: row.release_year, count: row.count })); res.render('mainpage', { yearData: yd, session: req.session }); }); });
server.js完整初始化代码
const express = require('express'); const mysql = require('mysql'); const session = require('express-session'); const MySQLStore = require('express-mysql-session')(session); const bodyParser = require('body-parser'); const cookieParser = require('cookie-parser'); const path = require('path'); const app = express(); var options = { host: 'localhost', user: 'root', password: '1019', database: 'user' }; var sessionStore = new MySQLStore(options); app.use(session({ secret: 'my key', resave: false, saveUninitialized: true, store: sessionStore })); const connection = mysql.createConnection({ host: 'localhost', user: 'root', password: '1019', database: 'user', port: '3306', }); app.use(express.static(path.join(__dirname, 'public'))); app.use(bodyParser.urlencoded({ extended: false })); app.use(cookieParser()); app.use(express.json()); app.use(express.urlencoded({ extended: true })); app.set('view engine', 'ejs'); app.set('views', path.join(__dirname, 'views')); app.listen(3000, () => { connection.connect(); console.log('Server is running on port 3000!'); });
触发的错误信息
ReferenceError: C:\Users\harry\Desktop\IWD Assignment\views\mainpage.ejs:78 76| <script> 77| >> 78| const yearData = <%- JSON.stringify(yearData) %>; 79| 80| 81| const yearChartWidth = 600; yearData is not defined at eval (eval at compile (C:\Users\harry\Desktop\IWD Assignment\node_modules\ejs\lib\ejs.js:673:12), <anonymous>:30:32) at mainpage (C:\Users\harry\Desktop\IWD Assignment\node_modules\ejs\lib\ejs.js:703:17) at tryHandleCache (C:\Users\harry\Desktop\IWD Assignment\node_modules\ejs\lib\ejs.js:274:36) at exports.renderFile [as engine] (C:\Users\harry\Desktop\IWD Assignment\node_modules\ejs\lib\ejs.js:491:10) at View.render (C:\Users\harry\Desktop\IWD Assignment\node_modules\express\lib\view.js:135:8) at tryRender (C:\Users\harry\Desktop\IWD Assignment\node_modules\express\lib\application.js:657:10) at Function.render (C:\Users\harry\Desktop\IWD Assignment\node_modules\express\lib\application.js:609:3) at ServerResponse.render (C:\Users\harry\Desktop\IWD Assignment\node_modules\express\lib\response.js:1049:7) at C:\Users\harry\Desktop\IWD Assignment\server.js:61:7 at Layer.handle [as handle_request] (C:\Users\harry\Desktop\IWD Assignment\node_modules\express\lib\router\layer.js:95:5)
错误原因分析
- MySQL连接时机错误:
connection.connect()放在app.listen()的回调中,导致路由中的connection.query()可能在数据库连接建立前就执行,查询回调无法触发,res.render()未执行,EJS模板拿不到yearData。 - 回调执行未确认:控制台无
yd日志,说明connection.query()的回调未进入,大概率是连接失败导致查询无法执行。 - 模板无兜底逻辑:EJS中直接使用
yearData,未判断变量是否存在,一旦后端未传入就直接报错。
修复方案
提前建立MySQL连接并处理连接错误
修改server.js的连接逻辑,确保服务启动前完成数据库连接:connection.connect((err) => { if (err) { console.error('Failed to connect to MySQL:', err); process.exit(1); // 连接失败直接终止服务 } console.log('Connected to MySQL successfully!'); }); app.listen(3000, () => { console.log('Server is running on port 3000!'); });添加日志确认回调执行状态
在路由的查询回调中添加日志,排查是否进入逻辑:connection.query(yearQuery, (err, yearResults) => { console.log('Query callback triggered'); // 确认回调是否执行 if (err) { console.error('Error fetching year data:', err); return res.status(500).send('Internal Server Error'); } yd = yearResults.map(row => ({ year: row.release_year, count: row.count })); console.log('yd data:', yd); // 输出数据确认格式 res.render('mainpage', { yearData: yd, session: req.session }); });给EJS模板添加兜底逻辑
在模板中先判断yearData是否存在,避免直接使用报错:<script> const yearData = <%- JSON.stringify(yearData || []) %>; // 后续d3代码... </script>验证数据库权限与SQL语句
用MySQL客户端执行SELECT release_year, COUNT(*) AS count FROM movies GROUP BY release_year,确认root用户有权限访问user数据库的movies表,且语句能返回有效数据。
内容的提问来源于stack exchange,提问作者mkbmob1004
相关产品推荐
相关产品推荐

