如何在Handlebars输出中去除重复的用户条目
在Handlebars中实现消息列表的用户去重
步骤1:注册Handlebars去重助手函数
在Express项目的Handlebars配置代码中,注册自定义助手uniqueUsers,用来提取并去重消息列表里的非当前用户:
const express = require('express'); const exphbs = require('express-handlebars'); const app = express(); // 配置Handlebars引擎 const hbs = exphbs.create({ helpers: { uniqueUsers: function(messages, currentUserId) { const seenUserIds = new Set(); const uniqueUsers = []; messages.forEach(msg => { // 筛选出消息中的对方用户 const targetUser = msg.fromUser._id.toString() === currentUserId ? msg.toUser : msg.fromUser; const userId = targetUser._id.toString(); if (!seenUserIds.has(userId)) { seenUserIds.add(userId); uniqueUsers.push(targetUser); } }); return uniqueUsers; } } }); app.engine('handlebars', hbs.engine); app.set('view engine', 'handlebars');
步骤2:在模板中调用助手函数
在Handlebars模板里,先用uniqueUsers处理原始消息列表,得到去重后的用户数组,再循环渲染:
{{#each (uniqueUsers messages currentUser._id)}} <div class="user-card"> <h3>{{this.name}}</h3> <!-- 其他用户相关内容渲染 --> </div> {{/each}}
关于路由处理报错的原因
你之前在路由的forEach里调用res.render,会触发多次响应发送操作——HTTP协议要求每个请求只能返回一次响应,所以会出现"Cannot set headers after they are sent to the client"错误。要么在路由里先完成所有数据处理再调用一次res.render,要么像上面这样把去重逻辑封装到Handlebars助手。
进阶:关联用户的最新消息
如果需要给每个去重后的用户绑定最新的一条消息,可以修改助手函数:
uniqueUsersWithLatestMsg: function(messages, currentUserId) { const userMsgMap = new Map(); messages.forEach(msg => { const targetUser = msg.fromUser._id.toString() === currentUserId ? msg.toUser : msg.fromUser; const userId = targetUser._id.toString(); // 仅保留该用户的最新消息(假设消息有createdAt时间字段) if (!userMsgMap.has(userId) || msg.createdAt > userMsgMap.get(userId).latestMsg.createdAt) { userMsgMap.set(userId, { user: targetUser, latestMsg: msg }); } }); return Array.from(userMsgMap.values()); }
模板中使用方式:
{{#each (uniqueUsersWithLatestMsg messages currentUser._id)}} <div class="user-item"> <p>{{this.user.name}}</p> <p class="last-msg">{{this.latestMsg.content}}</p> </div> {{/each}}
内容的提问来源于stack exchange,提问作者Christian Hustert
相关产品推荐
相关产品推荐

