You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Express.js中合并不同时间接收的多个请求对象?

在Express.js中合并间隔到达的多个请求

这个需求我做项目时碰到过好几次,核心就是要在多个请求之间暂存数据,等凑齐需要的用户信息和问题后再合并处理。下面给你两种实用的实现思路,分别对应单实例和分布式场景:

1. 单实例场景:用内存存储暂存数据

如果你的Express服务是单进程单实例部署的,可以直接用全局的Map来临时存储请求数据,记得加上超时清理避免内存泄漏。

首先得有一个唯一标识来关联同一个用户的多个请求——比如前端请求里带的userId、session ID,或者前端生成的traceId(每次用户发起操作时生成,所有相关请求都带这个ID)。

示例代码如下:

const express = require('express');
const app = express();
app.use(express.json());

// 全局临时存储,key是唯一标识,value是暂存的请求数据
const tempStore = new Map();
// 超时清理:10秒后自动删除未完成的暂存数据
const CLEANUP_TIMEOUT = 10000;

// 处理用户信息请求
app.post('/user-info', (req, res) => {
  const { traceId, userInfo } = req.body;
  if (!traceId) {
    return res.status(400).send('必须提供traceId关联请求');
  }

  // 存用户信息到临时存储
  tempStore.set(traceId, {
    userInfo,
    createdAt: Date.now()
  });

  // 设置超时清理
  setTimeout(() => {
    if (tempStore.has(traceId)) {
      tempStore.delete(traceId);
    }
  }, CLEANUP_TIMEOUT);

  res.send('用户信息已暂存');
});

// 处理用户问题请求,并合并数据
app.post('/user-question', (req, res) => {
  const { traceId, question } = req.body;
  if (!traceId) {
    return res.status(400).send('必须提供traceId关联请求');
  }

  const storedData = tempStore.get(traceId);
  if (!storedData?.userInfo) {
    return res.status(404).send('未找到关联的用户信息,请先提交用户信息');
  }

  // 合并数据
  const combinedData = {
    ...storedData.userInfo,
    question
  };

  // 这里可以做后续处理,比如存入数据库、调用业务接口等
  console.log('合并后的完整数据:', combinedData);

  // 处理完删除暂存数据,避免内存占用
  tempStore.delete(traceId);

  res.send('数据合并完成,已处理');
});

app.listen(3000, () => console.log('服务启动在3000端口'));

2. 多实例/分布式场景:用Redis做共享缓存

如果你的Express服务是多进程或者集群部署的,内存存储就不适用了(每个实例的内存是独立的),这时候需要用Redis这类共享缓存来暂存数据,同样要设置过期时间。

首先安装Redis客户端:

npm install redis

示例代码:

const express = require('express');
const { createClient } = require('redis');
const app = express();
app.use(express.json());

// 连接Redis
const redisClient = createClient({
  url: 'redis://localhost:6379' // 换成你的Redis地址
});
redisClient.connect().catch(console.error);

const EXPIRE_TIME = 10; // 过期时间10秒

// 处理用户信息请求
app.post('/user-info', async (req, res) => {
  const { traceId, userInfo } = req.body;
  if (!traceId) {
    return res.status(400).send('必须提供traceId关联请求');
  }

  // 存到Redis,设置过期时间
  await redisClient.setEx(traceId, EXPIRE_TIME, JSON.stringify({ userInfo }));

  res.send('用户信息已暂存');
});

// 处理用户问题请求,合并数据
app.post('/user-question', async (req, res) => {
  const { traceId, question } = req.body;
  if (!traceId) {
    return res.status(400).send('必须提供traceId关联请求');
  }

  // 从Redis取用户信息
  const storedStr = await redisClient.get(traceId);
  if (!storedStr) {
    return res.status(404).send('未找到关联的用户信息,或已过期');
  }
  const storedData = JSON.parse(storedStr);

  // 合并数据
  const combinedData = {
    ...storedData.userInfo,
    question
  };

  // 后续业务处理
  console.log('合并后的完整数据:', combinedData);

  // 删除Redis中的暂存数据
  await redisClient.del(traceId);

  res.send('数据合并完成,已处理');
});

app.listen(3000, () => console.log('服务启动在3000端口'));

关键注意事项

  • 唯一标识的必要性:必须要有traceId或者类似的标识来关联同一个用户的多个请求,否则无法区分哪些请求属于同一组。
  • 超时清理/过期时间:一定要设置超时,避免无效数据一直占用内存或缓存。
  • 异常处理:实际项目中要加上Redis连接失败、数据解析错误等异常捕获,避免服务崩溃。

内容的提问来源于stack exchange,提问作者Jatin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:19:14