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

如何在Next.js中为API创建全局错误处理器?

Next.js API 错误处理优化方案(告别重复try-catch)

核心思路:封装统一的错误捕获逻辑

你当前的问题是每个API接口都要手动写try-catch并传入errorHandler,解决这个问题的关键是把错误捕获逻辑封装成通用工具,让所有API路由自动复用,无需重复编写。

1. 封装异步处理包装函数

这是最通用的方案,兼容所有Next.js版本。写一个工具函数,把API的业务逻辑包裹进去,自动捕获异步错误并传给你的errorHandler。

代码示例:

首先创建utils/asyncHandler.js:

const asyncHandler = (fn) => (req, res, next) => {
  // 自动捕获异步函数的错误,传给next交给errorHandler处理
  Promise.resolve(fn(req, res, next)).catch(next);
};

module.exports = asyncHandler;

保留你的errorHandler(可微调优化),放在middleware/errorHandler.js:

const errorHandler = (err, req, res, next) => {
  const statusCode = err.statusCode || 500;
  const isDevelopment = process.env.NODE_ENV === 'development';
  const responseMessage = isDevelopment ? `请求无效:${err.message}` : '服务器内部错误';
  
  return res.status(statusCode).json({
    status: false,
    message: responseMessage,
    // 开发环境额外返回错误栈,方便调试
    ...(isDevelopment && { stack: err.stack })
  });
};

module.exports = errorHandler;

在API路由中使用:

比如pages/api/user.js:

import asyncHandler from '../../utils/asyncHandler';
import errorHandler from '../../middleware/errorHandler';

// 可选:自定义错误类,更规范地传递错误信息和状态码
class AppError extends Error {
  constructor(message, statusCode) {
    super(message);
    this.statusCode = statusCode;
    Error.captureStackTrace(this, this.constructor);
  }
}

// 业务逻辑直接写在asyncHandler包裹的函数里,不用手动try-catch
const userHandler = asyncHandler(async (req, res) => {
  if (req.method === 'GET') {
    // 模拟业务错误
    throw new AppError('请求的用户不存在', 404);
    // 正常逻辑示例:
    // res.status(200).json({ status: true, data: { id: 1, name: '张三' } });
  } else {
    throw new AppError('不支持该请求方法', 405);
  }
});

// 绑定错误处理中间件
export default (req, res) => userHandler(req, res, errorHandler);

2. 全局API中间件(Next.js 12+)

如果你的项目用Next.js 12及以上版本,可以用API路由中间件实现全局错误处理,不用每个路由单独绑定errorHandler。

代码示例:

在pages/api/_middleware.js中创建全局中间件:

import asyncHandler from '../../utils/asyncHandler';
import errorHandler from '../../middleware/errorHandler';

export default asyncHandler(async (req, event) => {
  // 先执行下游的API路由逻辑
  const response = await event.next();
  
  // 捕获下游返回的错误,交给errorHandler处理
  if (response.status >= 400 && response.error) {
    return errorHandler(response.error, req, response, () => {});
  }
  
  return response;
});

这样所有pages/api/下的路由都会自动应用这个错误处理逻辑,无需每个路由单独配置。

3. App Router 中的错误处理(Next.js 13+)

如果用Next.js 13+的App Router,除了包装函数外,还可以用error.js边界组件实现局部或全局的错误捕获:

单个API路由内的简化处理:

比如app/api/user/route.js:

import { NextResponse } from 'next/server';

class AppError extends Error {
  constructor(message, statusCode) {
    super(message);
    this.statusCode = statusCode;
  }
}

export async function GET() {
  try {
    throw new AppError('用户不存在', 404);
    // 正常逻辑:
    // return NextResponse.json({ status: true, data: { id: 1 } });
  } catch (err) {
    const statusCode = err.statusCode || 500;
    const isDevelopment = process.env.NODE_ENV === 'development';
    const message = isDevelopment ? `请求无效:${err.message}` : '服务器内部错误';
    
    return NextResponse.json({ status: false, message }, { status: statusCode });
  }
}

全局API错误边界:

在app/api/error.js中创建全局错误组件(仅客户端生效,适合前端展示错误):

'use client';
import { useEffect } from 'react';

export default function Error({ error, reset }) {
  useEffect(() => {
    // 可选:上报错误到监控平台
    console.error('API错误:', error);
  }, [error]);

  return (
    <div className="p-4">
      <h2>服务器出错了</h2>
      <p>{process.env.NODE_ENV === 'development' ? error.message : '请稍后重试'}</p>
      <button onClick={() => reset()} className="mt-2 px-4 py-2 bg-blue-500 text-white rounded">
        重新加载
      </button>
    </div>
  );
}

总结

  • 异步包装函数:最灵活,兼容所有版本,快速解决重复try-catch问题。
  • 全局API中间件:Next.js 12+适用,一次性配置所有API路由的错误处理。
  • App Router 错误边界:Next.js 13+适用,结合React错误边界实现前后端统一错误展示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 01:41:04