Next.js13使用fetch获取数据报错:Error: fetch failed
问题:Next.js 13 + Node.js 中偶现
fetch failed (ECONNRESET) 错误 环境信息
- Next.js v13.4.4
- Node.js v18.16.0(v16.08版本也存在相同问题)
错误日志
Sliders TypeError: fetch failed at Object.fetch (node:internal/deps/undici/undici:11457:11) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) { cause: Error: read ECONNRESET at TLSWrap.onStreamRead (node:internal/stream_base_commons:217:20) at TLSWrap.callbackTrampoline (node:internal/async_hooks:130:17) { errno: -4077, code: 'ECONNRESET', syscall: 'read' } } - error TypeError: fetch failed - error TypeError: fetch failed digest: "2026204822"
相关代码
接口调用方法 (mainSliderFetcher)
import errorMessage from "../errorMessage.json"; import { MainSliderType } from "@/app/types/response/slider"; const serverUrl = process.env.SERVERURL; export const mainSliderFetcher = async (): Promise<MainSliderType[]> => { try { const responses = await fetch(`${serverUrl}/sliders/`, { method: "GET", headers: { "Content-Type": "application/json", }, cache: "no-store", }); if (!responses.ok) { throw new Error(errorMessage.fetchError); } else return responses.json(); } catch (err) { console.log("sliders", err); throw new Error(errorMessage.fetchError); } };
页面调用代码 (page.tsx)
export default async function Home() { const getSliders = mainSliderFetcher(); const getBanners = mainBannersFetcher(); const [sliders, banners] = await Promise.all([getSliders, getBanners]); return ( <main className="flex min-h-screen flex-col items-center"> <MainCarousel data={sliders} /> <div className="flex flex-col px-4 lg:px-16"> <TopBanners data={banners} /> <SmallAbout /> </div> </main> ); }
解决方案建议
1. 添加重试机制
ECONNRESET多为连接被意外重置,针对这类错误添加重试逻辑可缓解偶发问题:
export const mainSliderFetcher = async (retries = 3): Promise<MainSliderType[]> => { try { const responses = await fetch(`${serverUrl}/sliders/`, { method: "GET", headers: { "Content-Type": "application/json", }, cache: "no-store", }); if (!responses.ok) { throw new Error(errorMessage.fetchError); } return responses.json(); } catch (err) { console.log("sliders", err); // 仅针对ECONNRESET错误重试 if (retries > 0 && (err as any).cause?.code === 'ECONNRESET') { console.log(`Retrying slider fetch, attempts left: ${retries - 1}`); return mainSliderFetcher(retries - 1); } throw new Error(errorMessage.fetchError); } };
2. 配置请求超时
避免请求长时间挂起导致连接被重置,添加超时控制:
export const mainSliderFetcher = async (): Promise<MainSliderType[]> => { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), 10000); // 10秒超时 try { const responses = await fetch(`${serverUrl}/sliders/`, { method: "GET", headers: { "Content-Type": "application/json", }, cache: "no-store", signal: controller.signal }); clearTimeout(timeoutId); if (!responses.ok) { throw new Error(errorMessage.fetchError); } return responses.json(); } catch (err) { clearTimeout(timeoutId); console.log("sliders", err); throw new Error(errorMessage.fetchError); } };
3. 排查后端服务
- 检查后端服务器日志,确认是否存在连接池耗尽、进程崩溃或资源不足的情况
- 验证后端接口的稳定性,测试单接口高频请求是否会出现类似问题
4. 基础配置校验
- 确认
process.env.SERVERURL格式正确,未遗漏http:///https://前缀,无多余斜杠 - 本地开发时关闭VPN、代理等可能干扰网络连接的工具
内容的提问来源于stack exchange,提问作者Hasan
相关产品推荐
相关产品推荐

