无法从MongoDB获取数据:Node.js+Express查询问题排查求助
MongoDB查询Promise无法解析导致路由无法获取数据排查
问题背景
已在MongoDB的users数据库users集合中存储用户数据,通过Studio 3T确认数据存在,但dal.js中的Promise无法解析,导致路由无法GET到数据。以下是相关代码:
dal.js
const { MongoClient } = require('mongodb'); // or as an es module: // import { MongoClient } from 'mongodb' // Connection URL const url = 'mongodb://localhost:27017'; const client = new MongoClient(url); async function main() { let db; // Use connect method to connect to the server await client.connect(); console.log('Connected successfully to db server'); db = client.db('users'); return db; } main() // create user accout function create(name, email, password, db) { db = client.db('users'); return new Promise((resolve,reject)=> { const collection = db.collection('users'); const doc = {name, email, password, balance: 0}; collection.insertOne(doc, {w:1}, function(err, result){ err ? reject(err) : resolve(doc); }) }) } // all users function all(db) { db = client.db('users'); return new Promise((resolve, reject) => { const customers = db .collection('users') .find({}) .toArray(function (err, docs) { err ? reject(err) : resolve(docs); console.log('Collection:',docs) }); }); } module.exports = {create, all};
server.js
var express = require('express'); var app = express(); var cors = require('cors'); var dal = require('./dal.js'); const corsOptions = { origin: 'http://localhost:3000', }; app.use(cors(corsOptions)); app.get("/", (req, resp) => { resp.send("App is Working"); }); app.get("/index", (req, resp) => { resp.send("hello world"); }); app.get("/accounts", (req, res) => { const docs = dal.all(); console.log(docs); res.send(docs); }); // create user account app.get('/account/create/:name/:email/:password/:balance', async function (req, res) { try { const user = await dal.create( req.params.name, req.params.email, req.params.password, req.params.balance ); console.log(user); res.send(user); } catch (error) { console.error(error); res.status(500).send('Internal Server Error'); } }); app.get('/account/all', async function (req, res) { try { const docs = await dal.all(); console.log(docs); res.send(docs); } catch (error) { console.error(error); res.status(500).send('Internal Server Error'); } }); app.listen(3001, () => console.log('Running on port 3001.'))
问题排查与修复
1. 客户端连接未确保完成就执行数据库操作
dal.js中调用main()后未处理连接结果,all和create函数直接调用client.db('users'),此时客户端可能还未完成连接,导致数据库操作失败,Promise无法正常解析。
2. 冗余的db参数覆盖
create和all函数都接收了db参数,但直接将其覆盖为client.db('users'),参数未发挥作用,且增加代码冗余。
3. 手动包裹Promise的冗余与风险
MongoDB的find().toArray()、insertOne()等方法本身已返回Promise,手动包裹Promise不仅冗余,还可能因回调逻辑疏漏导致错误捕获不及时。
4. /accounts路由未处理异步逻辑
该路由直接返回dal.all()的Promise对象给前端,而非实际查询到的数据,前端无法解析有效内容。
修正后的代码示例
dal.js
const { MongoClient } = require('mongodb'); const url = 'mongodb://localhost:27017'; const client = new MongoClient(url); let dbInstance; // 单例模式确保数据库连接仅初始化一次 async function connectToDB() { if (!dbInstance) { await client.connect(); console.log('Connected successfully to db server'); dbInstance = client.db('users'); } return dbInstance; } // 创建用户账户 - 使用原生Promise简化代码 async function create(name, email, password) { const db = await connectToDB(); const collection = db.collection('users'); const doc = { name, email, password, balance: 0 }; await collection.insertOne(doc, { w: 1 }); return doc; } // 获取所有用户 - 直接使用toArray返回的Promise async function all() { const db = await connectToDB(); const docs = await db.collection('users').find({}).toArray(); console.log('Collection:', docs); return docs; } module.exports = { create, all };
server.js 中修复/accounts路由
app.get("/accounts", async (req, res) => { try { const docs = await dal.all(); console.log(docs); res.send(docs); } catch (error) { console.error(error); res.status(500).send('Internal Server Error'); } });
修正说明
- 新增
connectToDB函数,采用单例模式确保数据库连接仅初始化一次,避免重复连接和未完成连接就执行操作的问题。 - 将
create和all改为async函数,直接使用MongoDB方法返回的Promise,简化代码同时提升可靠性。 - 移除冗余的
db参数,统一通过connectToDB获取数据库实例。 - 修复
/accounts路由的异步处理逻辑,使用async/await等待数据返回后再响应前端。
内容的提问来源于stack exchange,提问作者Sar
相关产品推荐
相关产品推荐

