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

Express.js实现请求超时后出现未捕获Promise拒绝警告求助

Express请求超时后避免重复响应的解决方案

你的问题核心是:超时回调已经发送了响应,后续异步任务完成后再次调用res.json()导致重复响应,触发uncaughtPromiseRejectionWarning。以下是具体解决思路和代码修改方案:

1. 标记请求状态,阻止后续响应

在超时回调中给请求对象添加一个超时标记,路由处理时先检查这个标记,若已超时则跳过响应发送。

修改超时中间件:

app.use(function(req, res, next){
    res.setTimeout(5000, function(){
        console.log('Request has timed out.');
        req.timedOut = true; // 标记请求已超时
        return res.json({success: false, message: "request timeout"});         
    });
    console.log("calling next");
    next();
});

修改路由处理逻辑:

app.get('/', async(req, res) => {
   const data = await asyncWork();
   if (req.timedOut) return; // 已超时则终止后续操作
   res.json(data);
});

2. 取消异步任务(优化方案)

如果异步任务支持取消,建议在超时后主动中止任务,避免不必要的资源消耗。Node.js 15+支持AbortController来实现这一点:

首先修改异步任务函数,接收中止信号:

const asyncWork = (signal) => {
  return new Promise((resolve,reject) => {
    const timer = setTimeout(() => {
      console.log("after 10 sec");
      resolve({"id": 1});
    },10000);

    // 监听中止信号,触发时清理资源并拒绝Promise
    signal.addEventListener('abort', () => {
      clearTimeout(timer);
      reject(new Error("Request timed out"));
    });
  });
};

然后更新中间件和路由:

app.use(function(req, res, next){
    const controller = new AbortController();
    req.signal = controller.signal;

    res.setTimeout(5000, function(){
        console.log('Request has timed out.');
        req.timedOut = true;
        controller.abort(); // 触发异步任务中止
        return res.json({success: false, message: "request timeout"});         
    });
    console.log("calling next");
    next();
});

app.get('/', async(req, res) => {
   try {
     const data = await asyncWork(req.signal);
     if (req.timedOut) return;
     res.json(data);
   } catch (err) {
     // 仅处理非超时中止的错误
     if (err.name !== 'AbortError') {
       res.status(500).json({success: false, message: "Server error"});
     }
   }
});

3. 全局捕获未处理的Promise拒绝(兜底方案)

为了避免控制台出现警告,可以在全局层面捕获未处理的Promise拒绝,作为兜底措施:

process.on('unhandledRejection', (reason, promise) => {
  console.log('未处理的Promise拒绝:', promise, '原因:', reason);
  // 可在此添加日志上报等操作
});

内容的提问来源于stack exchange,提问作者AYUSH KUMAR ARYAL

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 00:13:32