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

Express待办应用高频POST请求致页面卡顿,如何用队列处理?

问题分析与解决方案

卡顿的核心原因

  1. 客户端重复请求轰炸:每次操作立刻发起POST请求,短时间内5-6次请求同时触发,浏览器并发连接池被占满,导致页面资源调度卡顿。
  2. MongoDB操作冗余:当前用findOne + save的方式更新,每次更新要先查询再写入,两次IO操作,连续触发时数据库压力陡增。
  3. 无请求去重/合并:连续操作其实只需要保存最终的待办状态,中间的多次更新都是无效的,白白消耗资源。

解决方案一:客户端先做请求合并(最快见效)

给sendData加防抖逻辑,让连续操作只发送最后一次的状态,避免无效请求:

// 防抖定时器变量
let debounceTimer = null;

function sendData(obj) {
  // 取消之前未发送的请求
  if (debounceTimer) clearTimeout(debounceTimer);
  
  debounceTimer = setTimeout(() => {
    fetch('/jsondata', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(obj),
    }).catch(error => console.log(error));
    console.log('db updated');
  }, 300); // 300ms内的连续操作合并成一次请求
}

还可以加上AbortController取消未完成的请求,避免旧请求覆盖新状态:

let abortController = null;
let debounceTimer = null;

function sendData(obj) {
  // 取消之前的请求和定时器
  if (abortController) abortController.abort();
  if (debounceTimer) clearTimeout(debounceTimer);
  
  abortController = new AbortController();
  debounceTimer = setTimeout(() => {
    fetch('/jsondata', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(obj),
      signal: abortController.signal
    }).catch(error => {
      if (error.name !== 'AbortError') console.log(error);
    });
    console.log('db updated');
  }, 300);
}

解决方案二:服务端用队列异步处理

如果必须保留每次操作的记录(或者防抖满足不了需求),可以用消息队列把更新任务异步化,让接口快速返回,后台慢慢处理更新:

  1. 先安装队列库,比如bull:
npm install bull
  1. 配置队列并修改接口:
const Queue = require('bull');
// 创建用户缓存更新队列
const updateCacheQueue = new Queue('user-cache-update');

// 处理队列任务
updateCacheQueue.process(async (job) => {
  const { email, newState } = job.data;
  // 用updateOne直接更新,比findOne+save高效
  await user.updateOne(
    { email: email },
    { 
      $set: {
        cachedState: newState,
        date: Date.now()
      }
    },
    { upsert: true } // 防止用户不存在的情况
  );
  console.log('user cache has been updated');
});

// 修改接口,把任务丢进队列就返回
app.post('/jsondata', function (req, res) {
  updateCacheQueue.add({
    email: currentUserEmail,
    newState: JSON.stringify(req.body)
  }, {
    // 同一个用户的任务,保留最新的即可,替换旧任务
    jobId: `user-cache-${currentUserEmail}`,
    removeOnComplete: true,
    removeOnFail: true
  });
  res.sendStatus(202); // 快速返回接受状态
});

解决方案三:MongoDB操作优化

不管用不用队列,都应该优化数据库操作,把findOne + save改成updateOne,减少一次IO:

async function updateUserCache(email, newState) {
  await user.updateOne(
    { email: email },
    { 
      $set: {
        cachedState: newState,
        date: Date.now()
      }
    },
    { upsert: true } // 可选,根据你的业务是否需要自动创建用户
  );
  console.log('user cache has been updated');
}

另外给email字段加索引,加快查询速度:

// 在用户模型里添加索引
userSchema.index({ email: 1 });

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 00:20:16