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

重复请求Express接口报Query was already executed错误原因

问题描述

我定义了如下Schema与Model:

const userSchema = new mongoose.Schema({
  name: String,
})

const UserModel = mongoose.model('User', userSchema, 'users')

我编写了如下Express中间件,接收一个query参数,对该参数执行await等待,将异步返回的结果挂载到req对象的gottenDocs属性上(即req.gottenDocs):

function getDocumentsMw(query) {
  return async (req, res, next) => {
    const dbRes = await query
    req.gottenDocs = dbRes
    
    next()
  }
}

随后定义了如下路由:

app.get(
  '/users',
  getDocumentsMw(UserModel.find({})), 
  (req, res, next) => {
    const gottenDoc = req.gottenDocs
    res.status(200).json({
      status: 'success',
      data: gottenDoc,
    })
})

首次发起 GET "/users" 请求时,接口正常返回如下响应,无任何异常:

{
  "status": "success",
  "data": []
}

但异常的是,第二次请求该路由时会抛出如下错误:

MongooseError: Query was already executed: User.find({})

错误截图

请问该问题是什么原因导致的?是Node.js的bug吗?比如是否存在响应发送后未将函数调用移出调用栈的问题?


问题原因

这不是Node.js的bug,是代码写法逻辑错误导致的。核心原因是Mongoose的Query实例是带状态的一次性对象,你在路由初始化阶段就执行了UserModel.find({}),生成的同一个Query实例被所有请求复用,才触发了重复执行的报错。

具体执行逻辑拆解:

  • Express服务启动加载路由时,会立刻执行getDocumentsMw(UserModel.find({}))这行代码,此时UserModel.find({})就已经生成了一个固定的Mongoose Query实例,传入中间件工厂的就是这一个实例,不会在请求到来时重新生成。
  • 第一次请求进入时,中间件对这个Query实例执行await,触发查询执行,拿到结果后这个Query就会被Mongoose标记为已执行状态。
  • 第二次及后续请求进入时,中间件还是对同一个已经执行过的Query实例执行await,Mongoose检测到重复执行行为,就会直接抛出Query was already executed错误。

修复方案

不要在路由初始化阶段就生成Query实例,改为传入一个返回Query的工厂函数,每次请求到来时再调用函数生成全新的Query实例执行即可。

修改后的中间件代码:

// 入参改为接收返回Query的工厂函数,而非直接接收Query实例
function getDocumentsMw(queryFactory) {
  return async (req, res, next) => {
    // 每次请求到来时执行工厂函数,生成全新的Query实例
    const dbRes = await queryFactory()
    req.gottenDocs = dbRes
    next()
  }
}

路由调用处对应修改,把直接传入Query改为传入返回Query的箭头函数:

app.get(
  '/users',
  getDocumentsMw(() => UserModel.find({})), 
  (req, res, next) => {
    const gottenDoc = req.gottenDocs
    res.status(200).json({
      status: 'success',
      data: gottenDoc,
    })
})

修改后每次请求都会生成独立的Query实例,每个实例仅执行一次查询,就不会再出现重复执行的报错。


内容的提问来源于stack exchange,提问作者Islam Y-

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 15:24:34