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

Next.js App Router如何抛出错误并在浏览器网络面板显示

在Next.js App Router中自定义响应状态码的解决方案

一、状态码不生效的核心修复方法

在App Router中,仅在组件内渲染错误内容不会改变HTTP响应状态码(默认仍为200),必须在服务器组件/路由处理逻辑中主动返回对应状态码的响应。以下是具体实现方式:

1. 直接返回自定义状态码响应

在page.js(服务器组件)中,当验证或API请求失败时,使用NextResponse构造指定状态码的响应:

// app/page.js
import { headers } from 'next/headers';
import { NextResponse } from 'next/server';
import getIsValidIP from './utils/getIsValidIP';
import getApi from './utils/getApi';

export default async function HomePage() {
  // 获取用户IP(适配反向代理场景)
  const headerList = headers();
  const userIP = headerList.get('x-forwarded-for') || headerList.get('remote-addr');
  
  // IP验证逻辑
  const isValid = await getIsValidIP(userIP);
  if (!isValid) {
    // 返回403状态码及错误信息
    return NextResponse.json({ error: 'IP地址不被允许访问' }, { status: 403 });
  }

  // API请求逻辑
  try {
    const data = await getApi('/api/data');
    return <div>{JSON.stringify(data)}</div>;
  } catch (err) {
    // 捕获API返回的502错误,返回对应状态码
    if (err.statusCode === 502) {
      return NextResponse.json({ error: '服务暂时不可用' }, { status: 502 });
    }
    // 其他错误默认返回500
    throw err;
  }
}

2. 结合自定义错误页面(可选)

如果需要渲染定制化错误页面,可在app/error.js中捕获错误并展示,同时确保服务器端已返回正确状态码:

// app/error.js(客户端组件)
'use client';

export default function Error({ error, reset }) {
  const statusCode = error.cause?.statusCode || 500;
  return (
    <div className="error-page">
      <h1>错误 {statusCode}</h1>
      <p>{error.message}</p>
      <button onClick={() => reset()}>重试</button>
    </div>
  );
}

二、getApi复用函数的优化建议

假设你的原始getApi函数仅处理基础GET请求,以下是针对性优化方案:

优化后的getApi函数

// utils/getApi.js
async function getApi(url, options = {}) {
  const baseUrl = process.env.NEXT_PUBLIC_API_URL;
  const defaultHeaders = {
    'Content-Type': 'application/json',
    // 可添加全局认证头,如:'Authorization': `Bearer ${getAuthToken()}`
  };

  // 合并配置,添加10秒超时
  const config = {
    method: options.method || 'GET',
    headers: { ...defaultHeaders, ...options.headers },
    ...(options.body && { body: JSON.stringify(options.body) }),
    signal: AbortSignal.timeout(10000)
  };

  try {
    const res = await fetch(`${baseUrl}${url}`, config);
    // 兼容JSON/文本格式的响应
    const responseData = await res.json().catch(() => res.text());

    if (!res.ok) {
      const error = new Error(`API请求失败: ${res.statusText}`);
      error.statusCode = res.status;
      error.data = responseData;
      throw error;
    }

    return responseData;
  } catch (err) {
    // 分类处理错误
    if (err.name === 'TimeoutError') {
      const timeoutErr = new Error('请求超时,请稍后重试');
      timeoutErr.statusCode = 408;
      throw timeoutErr;
    }
    if (!err.statusCode) {
      const networkErr = new Error('网络连接失败,请检查网络');
      networkErr.statusCode = 0;
      throw networkErr;
    }
    throw err;
  }
}

export default getApi;

优化说明

  • 超时控制:通过AbortSignal.timeout添加10秒超时,避免请求无限挂起
  • 错误信息增强:抛出的错误携带statusCode和响应数据,方便上层根据状态码返回对应HTTP响应
  • 灵活配置:支持自定义请求方法、头信息、请求体,适配POST/PUT等场景
  • 响应兼容:自动处理JSON和文本格式的API响应
  • 错误分类:区分超时错误、网络错误、HTTP错误,提供更明确的错误提示

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 18:40:28