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

如何在res.send()后干净终止Node.js API中间件代码执行?

问题

我在某API端点实现了验证会话有效性的中间件verifySession,这个中间件会调用validateObjectId函数检查传入的MongoDB ObjectId是否合法。我希望当validateObjectId检测到无效Id时,能终止verifySession的后续执行。

但目前即使返回了错误响应,后续的console.log及正常流程代码仍会执行,导致出现“HTTP响应已结束,无法添加内容”的报错。我尝试过添加或移除return关键字,也知道可以把后续逻辑放在validateObjectId的.then()中,但这会降低代码可读性。我希望在函数顶部的判断逻辑处就能终止整个函数,请问我哪里出错了?

// EDIT 1 BEGIN
/**
 * 
 * @param {mongoose.Types.ObjectId} objectId Argument passed in must be a string of 12 bytes or a string of 24 hex characters or an integer.
 * @returns A rejected Promise if the value passed is not a valid MongoDB ObjectId.
 */
const validateObjectId = async (objectId) => {
  return new Promise((resolve, reject) => {
    // Check if the passed-in id is a valid MongoDB ObjectId. Return with an error of it's not.
    if (!mongoose.Types.ObjectId.isValid(objectId)) {
      reject({
        "error": ERROR_MESSAGES.INVALID_OBJECTID,
        "errorCode": ERROR_CODES.INVALID_OBJECTID
      });
    }
    resolve(objectId);
  })
}

// EDIT 1 END


// Verify Refresh Token Middleware (which will be verifying the session)
let verifySession = async (req, res, next) => {
  // Grab the refresh token from the request header.
  let refreshToken = req.header('x-refresh-token');

  // Grab the _id from the request header.
  let _id = req.header('_id');

  console.log('ObjectId: ', _id);

  await validateObjectId(_id)
    .catch((err) => {
      console.log('GOT HEREEEEEEEEEEEEEE', err);
      // return res.send(err);
      return res.status(STATUS_CODES.UNAUTHORIZED).send(err);
    });

    console.log('GOT HERE BUT SHOULD NOT HAVE');
  // Verify the session.
}
解决方案

问题出在**await搭配.catch()的错误处理逻辑**:.catch()会捕获Promise的reject并返回一个resolved状态的Promise,所以即使validateObjectId抛出错误,await之后的代码依然会继续执行。

推荐处理方式:用try/catch替代.catch()

把await逻辑放到try/catch块中,捕获错误后执行return就能直接终止后续代码,同时保持代码可读性:

// Verify Refresh Token Middleware (which will be verifying the session)
let verifySession = async (req, res, next) => {
  // Grab the refresh token from the request header.
  let refreshToken = req.header('x-refresh-token');

  // Grab the _id from the request header.
  let _id = req.header('_id');

  console.log('ObjectId: ', _id);

  try {
    await validateObjectId(_id);
  } catch (err) {
    console.log('GOT HEREEEEEEEEEEEEEE', err);
    return res.status(STATUS_CODES.UNAUTHORIZED).send(err);
  }

  // 仅当ObjectId验证通过时,才会执行以下代码
  console.log('验证通过才会执行这里');
  // Verify the session.
}

额外优化:简化validateObjectId函数

你的validateObjectId是async函数,没必要手动封装Promise,直接抛出错误即可:

const validateObjectId = (objectId) => {
  if (!mongoose.Types.ObjectId.isValid(objectId)) {
    throw {
      "error": ERROR_MESSAGES.INVALID_OBJECTID,
      "errorCode": ERROR_CODES.INVALID_OBJECTID
    };
  }
  return objectId;
}

(如果要保持async定义,直接throw也会被自动转为reject状态的Promise)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 16:45:07