Next.js拉取MongoDB数据时报错无法解构undefined的db属性
报错含义解释
你遇到的TypeError: cannot destructure property 'db' of '(intermediate value)' as it is undefined报错,是对象解构操作的目标值非法导致的。
代码中const {db} = await dbConnect()使用了ES6对象解构语法,预期await dbConnect()会返回一个带db属性的对象,解构后把db属性的值赋值给同名变量。当await dbConnect()的返回值是undefined时,JS引擎无法从undefined上读取属性,就会抛出这个类型错误。
问题根因
dbConnect函数没有稳定返回带db属性的对象:- 当检测到已存在数据库连接时,直接执行无返回值的
return;,返回结果为undefined - 首次建立连接时,
mongoose.connect的返回值被存在函数内部的局部变量db中,没有对外返回,调用方拿不到连接实例
- 当检测到已存在数据库连接时,直接执行无返回值的
- 数据查询逻辑存在额外问题:
- Mongoose的
connect方法返回的是Mongoose实例本身,不能直接调用collection()方法,需要通过实例上的connection.db拿到原生MongoDB驱动的数据库实例,才能操作集合 find()方法默认返回游标对象,必须调用.toArray()才能拿到实际的文档数组,直接序列化游标拿不到有效数据
- Mongoose的
修复步骤
- 修改
dbConnect.js,缓存连接状态和数据库实例,保证每次调用都返回带db属性的连接对象:
import mongoose from "mongoose"; const connect = { isConnected: false, db: null }; async function dbConnect() { // 已存在有效连接时直接返回缓存的实例 if (connect.isConnected && connect.db) { return connect; } // 首次连接时初始化连接、缓存状态和db实例 const mongooseInstance = await mongoose.connect(process.env.MONGO_URI); connect.isConnected = mongooseInstance.connection.readyState === 1; connect.db = mongooseInstance.connection.db; return connect; } export default dbConnect;
注:Mongoose 6.0及以上版本默认开启
useNewUrlParser、useUnifiedTopology配置,无需手动传入配置项。
- 修改
getServerSideProps中的查询逻辑,补全游标转数组的操作:
import dbConnect from '../utils/connectMongoDB' export async function getServerSideProps(context){ const {db} = await dbConnect(); // find()返回游标,调用toArray()拿到文档数组 const data = await db.collection("gcompanies").find({}).toArray(); const companies = JSON.parse(JSON.stringify(data)); return { props: { companies }, } }
内容的提问来源于stack exchange,提问作者Gayatri Belhekar
相关产品推荐
相关产品推荐

