Next.js连接MongoDB Atlas获取电影数据遇404及JSON解析错误
问题解决:Next.js调用MongoDB Atlas API出现404和JSON解析错误
核心问题分析
- 404错误说明API路由未被正确识别,Next.js返回了默认的404 HTML页面,导致后续JSON解析失败(HTML不是有效JSON格式)。
- 同时存在数据库连接依赖缺失、Schema与集合字段不匹配的潜在问题,即使路由正常也可能无法返回正确数据。
步骤1:确认API路由文件路径正确性
Next.js的API路由必须放在项目根目录的pages/api文件夹下,文件名直接对应路由路径。
- 确保你的
movies.ts文件路径是pages/api/movies.ts,如果路径错误(比如放在src/api但未配置src为根目录,或放在其他无关文件夹),会直接触发404。
步骤2:修复数据库连接代码的缺失依赖
你的数据库连接文件utils/db.js中缺少mongoose导入,会导致连接失败:
// 补充mongoose导入 import mongoose from 'mongoose'; import { config } from 'dotenv'; config(); const MONGODB_URI = process.env.MONGODB_URI; if (!MONGODB_URI) { throw new Error('Please define the MONGODB_URI environment variable'); } interface Cached { conn: typeof mongoose | null; promise: Promise<typeof mongoose> | null; } let cached: Cached = (global as any).mongoose; if (!cached) { cached = (global as any).mongoose = { conn: null, promise: null }; } async function connectToDatabase() { if (cached.conn) { return cached.conn; } if (!cached.promise) { cached.promise = mongoose.connect(MONGODB_URI as string).then((mongoose) => { return mongoose; }); } cached.conn = await cached.promise; return cached.conn; } export default connectToDatabase;
步骤3:修正Mongoose Schema与集合字段匹配
你使用的是MongoDB Atlas的sample_mflix.movies集合,字段为title、year、runtime,但原Schema错误添加了releaseYear且缺少runtime字段,会导致查询数据异常:
// 修改后的/api/movies.ts import type { NextApiRequest, NextApiResponse } from 'next'; import connectToDatabase from '../../utils/db'; import mongoose, { Model } from 'mongoose'; interface IMovie extends mongoose.Document { title: string; year: number; runtime: number; } // 匹配sample_mflix.movies的实际字段 const movieSchema = new mongoose.Schema({ title: { type: String, required: true }, year: { type: Number, required: true }, runtime: { type: Number, required: true }, // 补充runtime字段 }); // Mongoose默认将模型名复数化,Movie对应movies集合,符合sample_mflix的集合名 const Movie: Model<IMovie> = mongoose.models.Movie || mongoose.model<IMovie>('Movie', movieSchema); export default async function handler(req: NextApiRequest, res: NextApiResponse) { try { await connectToDatabase(); // 指定返回字段,减少冗余数据 const movies = await Movie.find({}, { title: 1, year: 1, runtime: 1, _id: 1 }); res.status(200).json(movies); } catch (err) { console.error('数据库查询错误:', err); res.status(500).json({ error: 'Failed to fetch movies' }); } }
步骤4:优化前端错误处理
在前端fetch时先判断响应状态,避免解析HTML导致的报错:
// 修改后的DataTable组件 import React, { useState, useEffect } from 'react' interface Movie{ _id: any; title: string; year: number; runtime: number; } function DataTable() { const [movies, setMovies] = useState<Movie[]>([]) const [error, setError] = useState<string | null>(null) useEffect(()=>{ async function fetchMovies() { try { const response = await fetch('/api/movies') if(!response.ok){ // 捕获404/500等错误,返回具体信息 const errorText = await response.text(); throw new Error(`请求失败: ${response.status} - ${errorText}`); } const data: Movie[] = await response.json() setMovies(data) setError(null) } catch (error) { console.error('failed to fetch',error) setError(error instanceof Error ? error.message : '未知错误') } } fetchMovies() }, []) if(error) { return <div className="p-4 text-red-500">{error}</div> } return ( <div className="p-4"> <h1 className="text-2xl font-bold mb-4">Movie List</h1> <div className="overflow-x-auto"> <table className="table-auto w-full border-collapse border border-gray-300"> <thead> <tr className="bg-gray-200"> <th className="border border-gray-300 px-4 py-2 text-left">Title</th> <th className="border border-gray-300 px-4 py-2 text-left">Year</th> <th className="border border-gray-300 px-4 py-2 text-left">Runtime</th> </tr> </thead> <tbody> {movies.map((movie) => ( {/* 用唯一的_id作为key,比index更稳定 */} <tr key={movie._id} className="even:bg-gray-100"> <td className="border border-gray-300 px-4 py-2">{movie.title}</td> <td className="border border-gray-300 px-4 py-2">{movie.year}</td> <td className="border border-gray-300 px-4 py-2">{movie.runtime}</td> </tr> ))} </tbody> </table> </div> </div> ); } export default DataTable
额外检查点
- 确认
.env文件中的MONGODB_URI正确,且MongoDB Atlas的IP白名单已添加你的本地IP(测试阶段可使用0.0.0.0/0)。 - 重启Next.js开发服务器,确保所有文件修改生效。
内容的提问来源于stack exchange,提问作者paramicia
相关产品推荐
相关产品推荐

