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

Node+MongoDB项目特定路由无响应,请求持续加载

问题描述

我正在开发一个练习用小型API,从MongoDB集合获取数据时遇到问题:访问特定路由(比如/authors)时,控制器无任何返回,API一直处于加载状态,没有响应。项目启动时数据库连接正常,控制台会输出连接成功提示,但请求/authors这类路由时既无结果也无报错,请求无限加载。之前做过类似的学习API运行正常,不知道当前问题出在哪。环境变量MONGODB_URI已配置集合名称。


代码文件

server.js

const express = require('express');
const mongodb = require('./db/connect');
const app = express();
const bodyParser = require('body-parser');

const port = process.env.PORT || 3000;

app.use(bodyParser.json()); 
app.use(bodyParser.urlencoded({ extended: true }));
app.use('/', require('./routes'));

process.on('uncaughtException', (err, origin) => {
  console.log(
    process.stderr.fd,
    `Caught exception: ${err}\n` + `Exception origin: ${origin}`
  );
});

mongodb.initDb((err) => {
  if (err) {
    console.log('数据库连接失败');
  } else {
    app.listen(port);
    console.log(`已连接数据库并监听端口 ${port}`);
  }
});

db/connect.js

const dotenv = require('dotenv');
dotenv.config();
const MongoClient = require('mongodb').MongoClient;

let _db;

const initDb = (callback) => {
  if (_db) {
    console.log('数据库已初始化!');
    return callback(null, _db);
  }
  MongoClient.connect(process.env.MONGODB_URI)
    .then((client) => {
      _db = client;
      callback(null, _db);
    })
    .catch((err) => {
      callback(err);
    });
};

const getDb = () => {
  if (!_db) {
    throw Error('数据库未初始化');
  }
  return _db;
};

module.exports = {
  initDb,
  getDb,
};

routes/index.js

const express = require('express');
const router = express.Router();

router.get('/', (req, res) => {
  res.send('运行中');
});

router.use('/authors', require('./authors'));

module.exports = router;

routes/authors.js

const express = require('express');
const router = express.Router();
const authorsController = require('../controllers/authorsController');

router.get('/', authorsController.getAll);
/*router.get('/:id', authorsController.getAuthorById);
router.get('/:id/books', authorsController.getAuthorBooks);
router.post('/', authorsController.addNewAuthor);
router.put('/:id', authorsController.updateAuthorInfo);
router.delete('/:id', authorsController.deleteAuthor);*/

module.exports = router;

controllers/authorsController.js

const mongodb = require('../db/connect');
const ObjectId = require('mongodb').ObjectId;

const getAll = async (req, res) => {
  const result = await mongodb.getDb().db().collection('authors').find();
  result.toArray((err, lists) => {
    if (err) {
      res.status(400).json({ message: err });
    }
    res.setHeader('Content-Type', 'application/json');
    res.status(200).json(lists);
  });
};

const getAuthorById = async (req, res) => {
  if (!ObjectId.isValid(req.params.id)) {
    res.status(400).json('Author ID格式无效');
  }
  const userId = req.params.id;
  const result = await mongodb
    .getDb()
    .db()
    .collection('authors')
    .find({ _id: userId });
  result.toArray((err, lists) => {
    if (condition) {
      res.status(400).json({ message: err });
    }
    res.setHeader('Content-Type', 'application/json');
    res.status(200).json(lists);
  });
};

module.exports = {
  getAll,
  getAuthorById,
};

package.json 依赖

{
  "body-parser": "^1.20.3",
  "dotenv": "^16.4.5",
  "express": "^4.21.1",
  "mongodb": "^6.9.0",
  "nodemon": "^3.1.7"
}

问题根源与修复方案

1. 异步模式混用导致响应阻塞

控制器中同时使用async/await和回调函数处理MongoDB游标,且未正确终止错误分支的响应流程,导致Express无法结束请求。

修复后的getAll方法:

const getAll = async (req, res) => {
  try {
    const collection = mongodb.getDb().db().collection('authors');
    const lists = await collection.find().toArray();
    res.setHeader('Content-Type', 'application/json');
    res.status(200).json(lists);
  } catch (err) {
    res.status(500).json({ message: err.message });
  }
};

2. getAuthorById中的语法错误与类型不匹配

  • 代码中if (condition)的condition未定义,会触发未捕获异常
  • 查询_id时使用字符串而非ObjectId类型,MongoDB无法匹配文档

修复后的getAuthorById方法:

const getAuthorById = async (req, res) => {
  if (!ObjectId.isValid(req.params.id)) {
    return res.status(400).json('Author ID格式无效');
  }
  try {
    const userId = new ObjectId(req.params.id);
    const collection = mongodb.getDb().db().collection('authors');
    const author = await collection.find({ _id: userId }).toArray();
    res.setHeader('Content-Type', 'application/json');
    res.status(200).json(author);
  } catch (err) {
    res.status(500).json({ message: err.message });
  }
};

3. 全局错误处理缺失

添加Express错误处理中间件,捕获未处理的异常并返回响应:
在server.js的所有路由之后添加:

app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).json({ message: '服务器内部错误' });
});

4. 数据库实例验证

确保MONGODB_URI包含目标数据库名称(例如mongodb://localhost:27017/bookstore),若未指定,需在db().db('your-db-name')中明确传入数据库名。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 07:54:51