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
相关产品推荐
相关产品推荐

