Fetch请求遇ECONNREFUSED时try/catch未捕获,致服务器崩溃求助
问题分析与解决方案
问题原因
你遇到的FetchError导致全站崩溃,核心问题不是getTournamentNews内部的try/catch失效,而是调用这个异步函数的代码没有正确处理Promise的拒绝状态。
在Node.js环境中,未被捕获的Promise拒绝会触发进程终止(默认行为)。如果Express启动脚本里调用getTournamentNews()时,既没有用await包裹在try/catch中,也没有附加.catch()处理错误,那么当服务器宕机触发网络错误时,这个未处理的Promise拒绝会直接导致Node进程崩溃,进而全站无法运行。
另外补充一点:你的代码未处理HTTP错误(比如500、404),因为fetch只有在网络层面失败时才会reject,HTTP状态码错误不会触发catch,这可能导致后续data.json()或数据处理逻辑出错,虽不是本次崩溃的主因,但也是潜在风险。
解决方案
1. 修复调用处的错误处理
确保在Express启动脚本中调用getTournamentNews时,正确处理异步错误:
// 示例修改后的启动逻辑 async function initScripts() { try { await getTournamentNews(); // 执行其他初始化逻辑 } catch (e) { console.error('初始化锦标赛新闻失败:', e); // 忽略错误,继续执行后续流程 } } // 调用初始化函数时也要兜底处理错误 initScripts().catch(e => console.error('初始化脚本整体出错:', e));
2. 优化getTournamentNews的健壮性
增加网络超时与HTTP错误处理
给fetch添加超时配置,同时判断HTTP响应状态,避免无效数据进入后续逻辑:
async function getTournamentNews() { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), 5000); // 5秒超时 try { let response = await fetch(`${process.env.WP_URL}/wp-json/wp/v2/posts/?per_page=10&_embed&_fields=content.rendered,categories&categories=638`, { signal: controller.signal }); clearTimeout(timeoutId); // 主动处理HTTP错误状态 if (!response.ok) { throw new Error(`HTTP请求失败,状态码: ${response.status}`); } let data = await response.json(); let dataObjectToArray = Object.values(data); // 用可选链避免属性不存在时抛出错误 let sortedData = dataObjectToArray.map(item => ({ content: item.content?.rendered, category: item.categories })); let clientNewsData = sortedData.filter(article => article.category?.[1] !== 284); return clientNewsData; } catch (e) { console.error('获取锦标赛新闻失败:', e); return null; } }
增加重试逻辑(可选)
如果需要在服务器恢复时自动重试,可以添加简单的重试机制:
async function getTournamentNews(retries = 2) { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), 5000); try { let response = await fetch(`${process.env.WP_URL}/wp-json/wp/v2/posts/?per_page=10&_embed&_fields=content.rendered,categories&categories=638`, { signal: controller.signal }); clearTimeout(timeoutId); if (!response.ok) { throw new Error(`HTTP请求失败,状态码: ${response.status}`); } let data = await response.json(); let dataObjectToArray = Object.values(data); let sortedData = dataObjectToArray.map(item => ({ content: item.content?.rendered, category: item.categories })); let clientNewsData = sortedData.filter(article => article.category?.[1] !== 284); return clientNewsData; } catch (e) { console.error(`获取锦标赛新闻失败,剩余重试次数: ${retries}`, e); if (retries > 0) { await new Promise(resolve => setTimeout(resolve, 1000)); // 间隔1秒重试 return getTournamentNews(retries - 1); } return null; } }
关键注意点
- 异步函数的错误必须被显式捕获,无论是用
await + try/catch还是.then().catch(),否则Node.js进程会因未处理的Promise拒绝而崩溃; fetch不会因HTTP错误状态码reject,必须手动判断response.ok;- 使用可选链操作符
?.避免数据结构异常导致的后续代码报错; - 超时配置可以防止请求因服务器无响应而长时间挂起。
内容的提问来源于stack exchange,提问作者Javi
相关产品推荐
相关产品推荐

