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

无法从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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 07:43:17