
本文介绍如何将按时间排序的聊天消息数组,依据连续的 userId 变化自动切分为多个“会话块”(即同一用户连续发送的消息归为一组),适用于前端消息渲染、气泡分组等典型场景。
本文介绍如何将按时间排序的聊天消息数组,依据连续的 `userid` 变化自动切分为多个“会话块”(即同一用户连续发送的消息归为一组),适用于前端消息渲染、气泡分组等典型场景。
在实现聊天界面时,仅按时间排序消息远远不够——还需将同一用户连续发送的多条消息聚合成一个逻辑块(例如左侧气泡组),当对方回复时开启新块(右侧气泡组),以此类推。这种“会话块分组”不同于传统按 userId 全局分组(如 groupBy(userId)),而是强调时序连续性:只有当 userId 发生变化且该变化是首次出现或与前一条不同时,才开启新数组。
核心思路是利用 JavaScript 的 Array.reduce() 遍历已排序的消息数组,动态维护分组结果。关键判断逻辑在于:当前消息的 userId 是否与前一条消息不同(首条消息默认开启新块)。满足条件则新建子数组并推入结果;否则追加到上一个子数组末尾。
以下为完整可运行示例(已适配现代 JavaScript 环境,无需模拟 ISODate):
const messages = [
{ content: 'content 1', userId: '123', targetUserId: '345', timestamp: new Date('2023-11-06T19:57:42.124Z') },
{ content: 'content 2', userId: '123', targetUserId: '345', timestamp: new Date('2023-11-06T19:58:42.124Z') },
{ content: 'content 3', userId: '123', targetUserId: '345', timestamp: new Date('2023-11-06T19:59:42.124Z') },
{ content: 'content 4', userId: '345', targetUserId: '123', timestamp: new Date('2023-11-06T20:00:42.124Z') },
{ content: 'content 5', userId: '345', targetUserId: '123', timestamp: new Date('2023-11-06T20:01:42.124Z') },
{ content: 'content 6', userId: '123', targetUserId: '345', timestamp: new Date('2023-11-06T20:02:42.124Z') },
{ content: 'content 7', userId: '123', targetUserId: '345', timestamp: new Date('2023-11-06T20:03:42.124Z') }
];
// ✅ 关键:确保数据已按 timestamp 升序排列(服务端或前端排序)
messages.sort((a, b) => a.timestamp - b.timestamp);
const groupedBlocks = messages.reduce((groups, current, index) => {
// 首条消息 或 当前 userId 与前一条不同 → 新建会话块
if (index === 0 || current.userId !== messages[index - 1].userId) {
groups.push([current]);
} else {
// 追加到上一个块
groups[groups.length - 1].push(current);
}
return groups;
}, []);
console.log(groupedBlocks);
// 输出 3 个子数组,分别对应用户 '123' → '345' → '123' 的连续发言块
⚠️ 重要注意事项:
-
排序前置:务必在分组前调用
.sort()按timestamp升序排列,否则分组逻辑失效; -
连续性敏感:此方法依赖相邻元素比较,不适用于跨时间窗口的用户状态合并(如需按对话线程聚合,请结合
conversationId字段); -
性能友好:
reduce时间复杂度为 O(n),无嵌套循环,适合千级以内消息实时处理; -
扩展建议:若需支持“空消息”过滤或自定义分组键(如
userId + targetUserId组合),可在判断条件中增强逻辑。
该方案轻量、可靠,是构建高交互性聊天 UI 的基础分组能力,可无缝集成至 React/Vue 渲染层,配合 CSS Flex 布局实现左右气泡自动对齐。










