EJS页面无限加载求助:路由文件错误定位
页面无限加载问题排查
我正在学习Web开发,跟着教程开发时页面出现无限加载的情况,怀疑问题出在路由文件里,但找不到具体错误,求帮忙指出。我已经核对过教程内容,检查了所有依赖,还是没解决问题,欢迎任何建议和批评,谢谢!
Model
const mongoose = require("mongoose"); const photoBasePath = "uploads/photoImages"; const photoSchema = new mongoose.Schema({ name: { type: String, required: true, }, description: { type: String, }, createdAt: { type: Date, required: true, default: Date.now, }, imageName: { type: String, required: true, }, tags: [ { type: mongoose.Schema.Types.ObjectId, ref: "Tag", }, ], }); module.exports = mongoose.model("Photo", photoSchema); module.exports.photoBasePath = photoBasePath;
Route
const { render } = require("ejs"); const express = require("express"); const router = express.Router(); const multer = require("multer"); const path = require("path"); const Photo = require("../models/photo"); const Tag = require("../models/tag"); const uploadPath = path.join("public", Photo.photoBasePath); const imageMimeTypes = ["image/jpeg", "image/png", "image/gif"]; const upload = multer({ dest: uploadPath, fileFilter: (req, file, callback) => { callback(null, imageMimeTypes.includes(file.mimetype)); }, }); //All Photos Route router.get("/", async (req, res) => { res.send("All Photos"); }); //New Photo Route router.get("/new", async (req, res) => { //res.send("New Photo"); renderNewPage(res, new Photo()); }); //Create Photo Route router.post("/", upload.single("photo"), async (req, res) => { const fileName = req.file != null ? req.file.filename : null; const photo = new Photo({ name: req.body.name, description: req.body.description, imageName: fileName, tags: req.body.tags, }); try { const newPhoto = await photo.save(); res.redirect("photos"); } catch { renderNewPage(res, photo, true); } }); async function renderNewPage(res, photo, hasError = false) { try { const tags = await Tag.find({}); const params = { tags: tags, photo: photo, }; const photo = new Photo(); if (hasError) params.errorMessage = "Error Creating Photo."; res.render("photos/new", params); } catch { renderNewPage(res, photo, true); } } module.exports = router;
View
new.ejs
<h2>New Photo</h2> <form action="/photos" method="POST" enctype="multipart/form-data"> <%- include('_form_fields') %> <a href="/photos">Cancel</a> <button type="submit">Create</button> </form>
_form_fields.ejs
<div> <label>Name</label> <input type="text" name="name" value="<%= photo.name %>" /> </div> <div> <label>Tags</label> <select name="tag"> <% tags.forEach(tag => { %> <% if (tag.id === photo.tag) { %> <option selected label="<%= tag.name %>" value="<%= tag.id %>"></option> <%} else {%> <option label="<%= tag.name %>" value="<%= tag.id %>"></option> <% } %> <% }) %> </select> </div> <div> <label>Photo</label> <input type="file" name="photo" /> </div> <div> <label>Description</label> <textarea type="description"> <%= photo.description %> </textarea> </div>
问题分析与修复
1. 路由函数无限递归触发死循环
renderNewPage的catch块中直接递归调用自身,没有任何终止条件。一旦Tag.find({})抛出错误(比如数据库连接失败),就会进入无限递归,导致服务器持续处理请求,页面无限加载。
修复:
替换递归调用,改为返回错误提示或重定向:
catch (err) { console.error(err); res.status(500).send("加载失败,请稍后重试"); // 或者重定向到列表页:res.redirect("/photos"); }
2. 函数内部重复声明变量覆盖参数
renderNewPage里重新声明const photo = new Photo();,直接覆盖了传入的photo参数,导致视图无法获取之前的表单数据,同时可能引发逻辑混乱。
修复:
删除这行重复声明的代码。
3. 视图与模型字段不匹配
- 模型中
tags是数组类型,但视图里select的name是tag(单数),提交后req.body.tag是单个ID,无法正确赋值给数组字段。 - 视图中判断
tag.id === photo.tag,但模型里不存在photo.tag属性,应该判断当前标签是否在photo.tags数组中。
修复(多选场景):
修改视图的select标签:
<select name="tags" multiple> <% tags.forEach(tag => { %> <option <%= photo.tags.includes(tag.id) ? 'selected' : '' %> label="<%= tag.name %>" value="<%= tag.id %>"></option> <% }) %> </select>
修复(单选场景):
如果只需要单选标签,修改模型的字段定义:
// 替换原有的tags数组字段 tag: { type: mongoose.Schema.Types.ObjectId, ref: "Tag", }
同时保持视图中select的name为tag,判断逻辑不变。
4. 图片字段必填性问题
模型中imageName设置了required: true,但如果用户未上传图片,fileName会是null,保存时会抛出错误,触发之前的递归问题。
修复:
要么允许imageName为空(去掉required: true),要么在上传逻辑中强制要求用户上传图片,或者设置默认图片路径。
内容的提问来源于stack exchange,提问作者Antoni Kaleta
相关产品推荐
相关产品推荐

