Express+EJS页面渲染后重复请求触发空值读取错误
问题描述
我有一个Express路由/vote/:id,逻辑是先从数据库查询数据,再渲染vote.ejs页面展示数据。页面能正常显示数据,但之后会额外发起2次请求,导致同一个TypeError错误重复出现两次,错误信息为“Cannot read properties of null (reading 'id')”。
相关代码
路由代码
app.get("/vote/:id", checkAuth, async (req, res) => { let botVote = await botDoc.findOne({ id: req.params.id }); renderWeb("vote.ejs", req, res, { bot: botVote }); });
EJS页面代码
<html lang="en"> <%- include('partials/head') %> <body> <%- include('partials/navbar') %> <br> <div class="container" style="padding-top: 69px; margin-left: 40%;"> <div class="vote"> <%= bot.id %> </div> </div> </div> <br><%- include('partials/footer') %> <script> </script> </body> </html>
报错信息
TypeError: D:\Users\ahmed\Documents\Coding\Projects\Beats'List2\views\vote.ejs:10 8| 9| 10| <%= bot.id %> 11| 12| 13| Cannot read properties of null (reading 'id') at eval ("D:\Users\ahmed\Documents\Coding\Projects\Beats'List2\views\vote.ejs":18:30) at vote (D:\Users\ahmed\Documents\Coding\Projects\Beats'List2\node_modules\ejs\lib\ejs.js:692:17) at tryHandleCache (D:\Users\ahmed\Documents\Coding\Projects\Beats'List2\node_modules\ejs\lib\ejs.js:272:36) at View.exports.renderFile [as engine] (D:\Users\ahmed\Documents\Coding\Projects\Beats'List2\node_modules\ejs\lib\ejs.js:489:10) at View.render (D:\Users\ahmed\Documents\Coding\Projects\Beats'List2\node_modules\express\lib\view.js:135:8) at tryRender (D:\Users\ahmed\Documents\Coding\Projects\Beats'List2\node_modules\express\lib\application.js:640:10) at Function.render (D:\Users\ahmed\Documents\Coding\Projects\Beats'List2\node_modules\express\lib\application.js:592:3) at ServerResponse.render (D:\Users\ahmed\Documents\Coding\Projects\Beats'List2\node_modules\express\lib\response.js:1012:7) at renderWeb (D:\Users\ahmed\Documents\Coding\Projects\Beats'List2\main.js:32:9) at processTicksAndRejections (node:internal/process/task_queues:96:5) TypeError: D:\Users\ahmed\Documents\Coding\Projects\Beats'List2\views\vote.ejs:10 8| 9| 10| <%= bot.id %> 11| 12| 13| Cannot read properties of null (reading 'id') at eval ("D:\Users\ahmed\Documents\Coding\Projects\Beats'List2\views\vote.ejs":18:30) at vote (D:\Users\ahmed\Documents\Coding\Projects\Beats'List2\node_modules\ejs\lib\ejs.js:692:17) at tryHandleCache (D:\Users\ahmed\Documents\Coding\Projects\Beats'List2\node_modules\ejs\lib\ejs.js:272:36) at View.exports.renderFile [as engine] (D:\Users\ahmed\Documents\Coding\Projects\Beats'List2\node_modules\ejs\lib\ejs.js:489:10) at View.render (D:\Users\ahmed\Documents\Coding\Projects\Beats'List2\node_modules\express\lib\view.js:135:8) at tryRender (D:\Users\ahmed\Documents\Coding\Projects\Beats'List2\node_modules\express\lib\application.js:640:10) at Function.render (D:\Users\ahmed\Documents\Coding\Projects\Beats'List2\node_modules\express\lib\application.js:592:3) at ServerResponse.render (D:\Users\ahmed\Documents\Coding\Projects\Beats'List2\node_modules\express\lib\response.js:1012:7) at renderWeb (D:\Users\ahmed\Documents\Coding\Projects\Beats'List2\main.js:32:9) at processTicksAndRejections (node:internal/process/task_queues:96:5)
解决方案
1. 定位额外请求来源
页面正常显示后出现的重复请求,大概率是浏览器自动发起的,比如:
- 浏览器默认请求
favicon.ico(若项目未配置该文件,请求会落到/vote/:id路由,此时req.params.id为favicon.ico,数据库查不到数据,botVote为null,渲染时触发错误) - 页面内引用的CSS、JS或图片路径错误,导致请求匹配到
/vote/:id路由
可以在路由中添加日志,打印请求参数和URL,确认请求详情:
app.get("/vote/:id", checkAuth, async (req, res) => { console.log(`请求ID: ${req.params.id}, 请求URL: ${req.url}`); let botVote = await botDoc.findOne({ id: req.params.id }); renderWeb("vote.ejs", req, res, { bot: botVote }); });
2. 处理查询结果为空的情况
无论请求来源如何,都要避免渲染时访问null对象的属性,有两种处理方式:
- 后端拦截:在路由中判断查询结果,为空则返回404或错误页面:
app.get("/vote/:id", checkAuth, async (req, res) => { let botVote = await botDoc.findOne({ id: req.params.id }); if (!botVote) { return res.status(404).send("数据不存在"); // 或渲染404页面:return res.render("404.ejs"); } renderWeb("vote.ejs", req, res, { bot: botVote }); });
- 前端防御:在EJS模板中添加判断,避免直接访问
bot.id:
<div class="vote"> <%= bot ? bot.id : "数据不存在" %> </div>
3. 解决favicon请求问题
如果是favicon导致的问题,可通过以下方式处理:
- 在项目根目录放置
favicon.ico文件 - 专门配置路由处理favicon请求:
app.get('/favicon.ico', (req, res) => res.status(204).end());
内容的提问来源于stack exchange,提问作者FROST MAN
相关产品推荐
相关产品推荐

