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

MongoDB Atlas连接Node.js时遇'dbItem is not defined'错误求助

解决MongoDB Atlas连接后ReferenceError: dbItem is not defined错误

问题描述

已创建MongoDB Atlas数据库,Node.js成功连接,但运行服务器时出现错误:ReferenceError: dbItem is not defined,dbItem是定义的集合常量。相关代码如下:

const express = require("express");
const bodyParser = require("body-parser");
const { MongoClient } = require("mongodb");

const app = express();

app.set('view engine', 'ejs');

app.use(bodyParser.urlencoded({extended: true}));
app.use(express.static("public"));

const uri =
 "mongodb+srv://username:1234321@cluster0.8imjcky.mongodb.net/?retryWrites=true&w=majority";

const client = new MongoClient(uri);

async function run() {
 try {
   const todolistDB = client.db("todolistDB");
   const dbItem = todolistDB.collection("Item");
  
   const defaultItems = [
     { item1: "welcome to your todolist" },
     { item2: "add new Item"},
     { item3: "delete item"}
   ];

const result = await dbItem.insertMany(defaultItems);
 console.log(`${result.insertedCount} documents were inserted`);
} finally {
 await client.close();
}
}
run().catch(console.dir);

app.get("/", function(req, res) {
  //const dbItem = app.locals.collection;
  dbItem.find({}, function(err, foundItems){
    res.render("list", {listTitle: "Today", newListItems: foundItems});
  });
});

应用已成功连接Atlas,且dbItem集合已在Atlas中创建,曾尝试在app.get函数前使用app.locals.collections = dbItem,但问题仍未解决。

问题根源

  • 作用域问题:dbItem是run函数内部的局部变量,app.get的回调函数处于外部作用域,无法访问该变量。
  • 连接关闭问题:run函数执行完毕后调用了client.close(),导致后续请求时MongoDB连接已关闭,即使能拿到dbItem也无法正常操作数据库。
  • 错误的app.locals赋值:之前直接在run函数外部给app.locals赋值,此时dbItem还未定义,赋值的是undefined,自然无法在路由中使用。

修正方案

完整修正代码

const express = require("express");
const bodyParser = require("body-parser");
const { MongoClient } = require("mongodb");

const app = express();

app.set('view engine', 'ejs');

app.use(bodyParser.urlencoded({extended: true}));
app.use(express.static("public"));

const uri =
 "mongodb+srv://username:1234321@cluster0.8imjcky.mongodb.net/?retryWrites=true&w=majority";

const client = new MongoClient(uri);

async function run() {
 try {
   // 显式建立MongoDB连接
   await client.connect();
   const todolistDB = client.db("todolistDB");
   const dbItem = todolistDB.collection("Item");
   // 将集合引用挂载到app.locals,供路由访问
   app.locals.dbItem = dbItem;
  
   const defaultItems = [
     { item: "welcome to your todolist" },
     { item: "add new Item"},
     { item: "delete item"}
   ];
   // 检查集合是否为空,避免重复插入默认数据
   const itemCount = await dbItem.countDocuments();
   if (itemCount === 0) {
     const result = await dbItem.insertMany(defaultItems);
     console.log(`${result.insertedCount} documents were inserted`);
   }
   // 数据库连接成功后再启动服务
   app.listen(3000, function() {
     console.log("Server started on port 3000");
   });
} catch(err) {
  // 捕获连接或数据库操作错误
  console.error("Database connection error:", err);
}
// 不在这里关闭client,保持长连接供服务持续使用
}
run().catch(console.dir);

app.get("/", async function(req, res) {
  try {
    // 从app.locals获取集合引用
    const dbItem = req.app.locals.dbItem;
    // 使用async/await处理异步查询,替代回调写法
    const foundItems = await dbItem.find({}).toArray();
    res.render("list", {listTitle: "Today", newListItems: foundItems});
  } catch(err) {
    console.error("Fetch items error:", err);
    res.status(500).send("Failed to load todolist items");
  }
});

关键修改说明

  • 保持数据库长连接:移除finally块中的client.close(),Express服务需要持续的数据库连接来处理后续请求。
  • 正确挂载集合引用:在run函数内部获取到dbItem后,再将其挂载到app.locals,确保路由能访问到有效的集合引用。
  • 异步操作优化:路由回调改为async函数,使用await处理MongoDB查询,这是MongoDB v4+推荐的写法,比回调更易维护。
  • 避免重复插入:添加集合文档数量检查,只有当集合为空时才插入默认数据,防止每次服务启动都重复添加相同内容。
  • 延迟启动服务:将app.listen放在run函数内部,确保数据库连接成功后再接收请求,避免请求时数据库尚未准备好。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 06:35:51