You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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)

错误原因分析

  1. MySQL连接时机错误:connection.connect()放在app.listen()的回调中,导致路由中的connection.query()可能在数据库连接建立前就执行,查询回调无法触发,res.render()未执行,EJS模板拿不到yearData。
  2. 回调执行未确认:控制台无yd日志,说明connection.query()的回调未进入,大概率是连接失败导致查询无法执行。
  3. 模板无兜底逻辑:EJS中直接使用yearData,未判断变量是否存在,一旦后端未传入就直接报错。

修复方案

  1. 提前建立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!');
    });
    
  2. 添加日志确认回调执行状态
    在路由的查询回调中添加日志,排查是否进入逻辑:

    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 });
    });
    
  3. 给EJS模板添加兜底逻辑
    在模板中先判断yearData是否存在,避免直接使用报错:

    <script>
      const yearData = <%- JSON.stringify(yearData || []) %>;
      // 后续d3代码...
    </script>
    
  4. 验证数据库权限与SQL语句
    用MySQL客户端执行SELECT release_year, COUNT(*) AS count FROM movies GROUP BY release_year,确认root用户有权限访问user数据库的movies表,且语句能返回有效数据。

内容的提问来源于stack exchange,提问作者mkbmob1004

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 10:39:52