MongoDB+Express服务报错:Cannot read properties of undefined (reading 'collection')
问题:MongoDB连接后db对象未定义导致接口报错
错误信息
访问http://localhost:3600/artifacts时触发以下错误:
TypeError: Cannot read properties of undefined (reading 'collection') at /home/gatwiri/MEAN/sbom-dataserver.js:41:6 at Layer.handle [as handle_request] (/home/gatwiri/MEAN/node_modules/express/lib/router/layer.js:95:5) at next (/home/gatwiri/MEAN/node_modules/express/lib/router/route.js:144:13) at Route.dispatch (/home/gatwiri/MEAN/node_modules/express/lib/router/route.js:114:3) at Layer.handle [as handle_request] (/home/gatwiri/MEAN/node_modules/express/lib/router/layer.js:95:5) at /home/gatwiri/MEAN/node_modules/express/lib/router/index.js:284:15 at param (/home/gatwiri/MEAN/node_modules/express/lib/router/index.js:365:14) at param (/home/gatwiri/MEAN/node_modules/express/lib/router/index.js:376:14) at Function.process_params (/home/gatwiri/MEAN/node_modules/express/lib/router/index.js:421:3) at next (/home/gatwiri/MEAN/node_modules/express/lib/router/index.js:280:10)
控制台输出:
GEThttp://localhost:3600/artifacts [HTTP/1.1 500 Internal Server Error 1ms] Content Security Policy: The page’s settings blocked the loading of a resource at http://localhost:3600/favicon.ico ("default-src").
问题代码
const express = require('express') const app = express() var db const dbName = 'my-test' const port = 3600 let table = 'artifact' const url = "mongodb://localhost:27017/" app.listen(port, function() { console.log('Listening on ' + port + '.') }) const MongoClient = require('mongodb').MongoClient app.route('/').get((req, res) => { res.send("Recognized endpoints on this server include '/artifacts' and '/artifacts/NAME'.") }) app.route('/artifacts').get((req, res) => { db.collection(table).find().toArray((err, artifact) => { if (err) throw err var artifacts = [] artifact.forEach((value) => { artifacts.push({scriptname: value.scriptname}) }) res.send(artifacts) }) }) app.route('/artifacts/:scriptname').get((req, res) => { const scriptname = req.params['scriptname'] db.collection(table).findOne({scriptname: scriptname}, function(err, artifact) { if (err) throw err res.send({ scriptname: artifact.scriptname, version: artifact.version, cdn: artifact.cdn }) }) }) MongoClient.connect(url, (err, client) => { const db = client.db(dbName); db.collection(table).find().toArray((err, artifact) => { if (err) throw err artifact.forEach((value) => { }) client.close() }) })
问题根源
- 全局
db变量未正确赋值:在MongoClient.connect回调中使用const db声明了局部变量,覆盖了全局的db,导致全局db始终为undefined,接口调用时自然无法读取collection属性。 - 连接后立即关闭客户端:回调中执行了
client.close(),关闭了MongoDB连接,即使db赋值成功,后续请求也无法操作数据库。 - 服务启动早于数据库连接:
app.listen在数据库连接前执行,可能出现请求到达时数据库还未完成连接的情况。
修复后的代码
const express = require('express') const app = express() var db const dbName = 'my-test' const port = 3600 let table = 'artifact' const url = "mongodb://localhost:27017/" const MongoClient = require('mongodb').MongoClient // 先配置路由 app.route('/').get((req, res) => { res.send("Recognized endpoints on this server include '/artifacts' and '/artifacts/NAME'.") }) app.route('/artifacts').get((req, res) => { db.collection(table).find().toArray((err, artifacts) => { if (err) { console.error(err); return res.status(500).send('Database error'); } const result = artifacts.map(value => ({ scriptname: value.scriptname })) res.send(result) }) }) app.route('/artifacts/:scriptname').get((req, res) => { const scriptname = req.params['scriptname'] db.collection(table).findOne({ scriptname: scriptname }, function(err, artifact) { if (err) { console.error(err); return res.status(500).send('Database error'); } if (!artifact) { return res.status(404).send('Artifact not found'); } res.send({ scriptname: artifact.scriptname, version: artifact.version, cdn: artifact.cdn }) }) }) // 连接数据库成功后再启动服务 MongoClient.connect(url, (err, client) => { if (err) { console.error('Failed to connect to MongoDB:', err); process.exit(1); } // 给全局db赋值,不要用const声明局部变量 db = client.db(dbName); console.log('Connected to MongoDB successfully'); // 数据库连接成功后启动服务 app.listen(port, function() { console.log('Listening on port ' + port + '.') }) })
关键修改说明
- 移除回调中
db的const声明,直接给全局db变量赋值,确保接口能访问到数据库实例。 - 删除
client.close(),保持MongoDB连接长期有效,供后续请求复用。 - 将
app.listen移到数据库连接成功的回调中,确保服务启动时数据库已就绪。 - 增加错误处理逻辑,避免直接
throw err导致服务崩溃,返回合适的HTTP状态码。
内容的提问来源于stack exchange,提问作者gatwirival
相关产品推荐
相关产品推荐

