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

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

额外检查点

  1. 确认.env文件中的MONGODB_URI正确,且MongoDB Atlas的IP白名单已添加你的本地IP(测试阶段可使用0.0.0.0/0)。
  2. 重启Next.js开发服务器,确保所有文件修改生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 09:08:13