Handlebars渲染电影数据重复问题求助(附代码)
核心问题排查
首先看你的代码,存在几个明显的问题点,直接导致重复渲染:
1. Handlebars变量名不匹配
你在路由中传递给模板的变量是generatedHTMLArrayFavorites,但Handlebars模板里遍历的却是generatedHTMLArray——变量名完全不一致,这要么导致渲染空数据,要么如果模板里的变量名是笔误,实际代码中存在其他重复赋值逻辑,都会引发异常渲染。
2. 中间件逻辑冗余且可能导致数据累加
你的中间件每次请求都会调用getMovieHTMLArrayFavorites()获取数据,即使session中已经存在缓存。如果getMovieHTMLArrayFavorites()内部是用全局数组累加数据(比如每次调用都往同一个数组push电影),而非每次从JSON文件重新读取并生成新数组,就会导致数组里的元素越来越多,重复渲染。
3. Session缓存逻辑不合理
你先获取新数据存到res.locals,再判断session是否为空,为空才存session。但路由里又直接取session中的旧数据——如果session已经存在,中间件获取的新数据完全没用到,既无法更新收藏列表,还可能因为session里的数据本身就是重复的,一直重复渲染。
具体修复步骤
步骤1:修正Handlebars变量名
把模板里的遍历变量改成和路由传递的一致:
{{#each generatedHTMLArrayFavorites}} {{{this}}} {{/each}}
步骤2:优化中间件逻辑
根据你的需求选择两种方案:
方案A:需要缓存收藏列表(不实时更新)
只有当session中没有数据时,才去获取并缓存,避免重复调用可能导致的数据累加:
const FavoriteMoviesArray = async (req, res, next) => { if (!req.session.generatedHTMLArrayFavorites) { // 仅首次请求时获取数据 const generatedHTMLArrayFavorites = await movieContainerCreator.getMovieHTMLArrayFavorites(); // 可选:对数组去重(根据电影ID等唯一标识) const uniqueMovies = [...new Map(generatedHTMLArrayFavorites.map(item => [item.movieId, item])).values()]; req.session.generatedHTMLArrayFavorites = uniqueMovies; res.locals.generatedHTMLArrayFavorites = uniqueMovies; } else { // 复用session缓存的数据 res.locals.generatedHTMLArrayFavorites = req.session.generatedHTMLArrayFavorites; } next(); };
方案B:需要实时更新收藏列表
放弃session缓存,每次请求都重新获取最新数据,并确保数据去重:
const FavoriteMoviesArray = async (req, res, next) => { const generatedHTMLArrayFavorites = await movieContainerCreator.getMovieHTMLArrayFavorites(); // 强制去重,避免JSON文件或函数内部的重复数据 const uniqueMovies = [...new Map(generatedHTMLArrayFavorites.map(item => [item.movieId, item])).values()]; res.locals.generatedHTMLArrayFavorites = uniqueMovies; next(); };
步骤3:修复路由逻辑
路由直接使用res.locals中的数据,保持逻辑统一:
app.get("/Favorite.html", redirectLogin, FavoriteMoviesArray, async function (req, res) { try { res.render("Favorite", { generatedHTMLArrayFavorites: res.locals.generatedHTMLArrayFavorites }); } catch (error) { console.error("Error:", error); res.status(500).send("Internal Server Error"); } });
步骤4:检查getMovieHTMLArrayFavorites()实现
确保这个函数每次都是从JSON文件重新读取并生成新数组,而不是往全局数组里追加元素。比如:
// 错误示例(累加数据) let globalMovies = []; async function getMovieHTMLArrayFavorites() { const data = await fs.readJSON('favorites.json'); globalMovies.push(...data); // 每次调用都累加 return globalMovies.map(movie => generateHTML(movie)); } // 正确示例(每次生成新数组) async function getMovieHTMLArrayFavorites() { const data = await fs.readJSON('favorites.json'); return data.map(movie => generateHTML(movie)); // 每次返回全新数组 }
内容的提问来源于stack exchange,提问作者Alex

