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

Node.js应用添加/api路由后崩溃:db未定义无法连接MongoDB

问题排查与解决方法

核心原因

问题出在模块加载顺序与异步初始化的冲突:
当你添加app.use('/api', routes)时,Node.js会同步加载路由模块,进而触发productAgent.ts的加载。而productAgent.ts在模块顶层直接执行了getCollection('products')——此时connectDB()还未完成(它是异步执行的,要等到app.listen前才会完成),全局变量db仍为undefined,调用db.collection()自然抛出TypeError。

移除路由配置时,路由相关模块不会被加载,也就不会触发getCollection的提前调用,因此应用能正常启动。


解决方法

方案1:延迟集合获取(推荐)

修改productAgent.ts,不在模块顶层初始化集合,改为在函数内部动态获取,确保只有请求触发时才调用getCollection(此时数据库已连接完成):

import { getCollection } from '../../db'
import { ObjectId } from 'mongodb'
import { IProduct } from '../../types/IProduct'

export const createProduct = async (parameters: IProduct): Promise<boolean> => {
    try {
     // 仅在函数执行时获取集合
     const collectionProduct = getCollection<IProduct>('products')
     const res= await collectionProduct.insertOne(parameters)
     return res.acknowledged
    } catch (error) {
        throw new Error('Error create product')
    }
}

方案2:数据库连接完成后再加载路由

修改index.ts,通过动态导入路由模块,确保只有数据库连接成功后才加载路由相关代码:

import express from 'express'
import cors from 'cors'
import { connectDB } from './db'
const port= process.env.port|| 5000
const app = express()

app.use(cors())
app.use(express.json())
app.get('/', (req, res) => res.send('Running'))    

connectDB().then(async () => {
    // 连接完成后动态导入路由
    const routes = await import('./routes')
    app.use('/api', routes.default)
    app.listen(port, () => console.log(`Running: http://localhost:${port}`))
}).catch(err => console.log(err))

方案3:给getCollection增加初始化检查

修改db.ts的getCollection函数,添加db存在性校验,避免无意义报错:

import { Db, Collection, Document } from 'mongodb'
import { MongoClient } from 'mongodb'

let db: Db
    
export const connectDB = async (): Promise<void> => {
  try {
    const uri = process.env.MONGO_URI as string
    const client = new MongoClient(uri)
    await client.connect()   
    db = client.db(process.env.DB_NAME)
  }catch(error) {
    console.log(error)
    throw error // 连接失败时抛出错误,避免应用带病运行
  }
}

export const getCollection = <T extends Document>(name: string): Collection<T> => {
  if (!db) {
    throw new Error('数据库未连接,请先执行connectDB()')
  }
  return db.collection<T>(name)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 00:19:52