Node.js Discord YouTube通知机器人依赖更新后出现ECONNRESET与404错误求助
错误原因
你碰到的报错分为两类,核心原因如下:
ECONNRESET错误:属于TCP连接被远程服务器强制断开,要么是你的代码短时间内并发请求YouTube接口次数过多被限流,要么是你服务器的网络环境访问YouTube不稳定。你现在用forEach遍历频道列表并发执行异步请求,所有请求几乎同时发出,并发量过高非常容易触发YouTube的访问限制。- 404状态码错误:是
rss-parser请求的RSS地址无效,要么是你拼接的RSS地址中的频道ID错误,要么是你配置的频道本身不存在/已删除。另外你代码里所有.catch()都是空的,吞掉了全部中间错误,无法定位具体出问题的请求,最终未捕获的404错误直接导致进程崩溃。
解决思路
1. 修复错误处理逻辑
把所有空的.catch()替换成实际的错误捕获逻辑,不要吞错误,至少要打印错误对应的频道信息,遇到错误直接返回null不要让错误上抛导致进程崩溃,示例修改如下:
// 以getLastVideo函数为例 async function getLastVideo(youtubeChannelName, rssURL){ try { const content = await parser.parseURL(rssURL); const tLastVideos = content.items.sort((a, b) => { const aPubDate = new Date(a.pubDate || 0).getTime(); const bPubDate = new Date(b.pubDate || 0).getTime(); return bPubDate - aPubDate; }); return tLastVideos[0] || null; } catch (err) { console.log(`[${youtubeChannelName}] 获取RSS失败:`, err.message); return null; } }
其他所有带异步请求的函数都按照这个逻辑修改,用try/catch替代混用的await + .then,逻辑更清晰也不容易漏处理错误。
2. 修复404问题
- 首先确认你配置的所有频道ID都是有效的,拼接RSS地址前先打印
channelInfos.id的值,对比你已知的正确频道ID看是否匹配。 - 修复
getYoutubeChannelIdFromURL函数的正则错误,正则里的斜杠需要转义,原代码的split(/(/channel/|/user/)/)写法是错误的,修改为:
function getYoutubeChannelIdFromURL(url) { let id = null; url = url.replace(/(>|<)/gi, "").split(/(\/channel\/|\/user\/)/); if(url[2]) { id = url[2].split(/[^0-9a-z_-]/i)[0]; } return id; }
这个错误会导致解析频道URL时拿不到正确的ID,拼接出来的RSS地址自然是404。
3. 修复ECONNRESET限流问题
- 替换
forEach并发请求逻辑,改成串行请求+间隔延迟,降低并发量,示例修改如下:
async function check(){ console.log("开始检查频道更新..."); // 把forEach换成for...of串行执行 for (const youtuber of youtubers) { let channelInfos = await getYoutubeChannelInfos(youtuber); if(!channelInfos) { console.log("[ERR] 无效的频道配置: "+youtuber); // 每个请求之间加1~2秒延迟 await new Promise(resolve => setTimeout(resolve, 1500)); continue; } let lastVideo = await checkVideos(channelInfos.raw.snippet.title, "https://www.youtube.com/feeds/videos.xml?channel_id="+channelInfos.id); if(!lastVideo) { await new Promise(resolve => setTimeout(resolve, 1500)); continue; } // 剩下的发通知逻辑不变 // ...原有发Embed的代码 // 处理完一个频道再等1.5秒再处理下一个 await new Promise(resolve => setTimeout(resolve, 1500)); } }
- 拉长全局检查的间隔时间,如果你原来设置的是5分钟检查一次,改成10~15分钟检查一次,进一步降低请求频率。
- 可以给网络请求加重试逻辑,单次请求失败后等待3秒再重试一次,最多重试2次,避免偶发的网络波动导致报错。
4. 其他检查点
确认你升级后的第三方依赖版本兼容,尤其是rss-parser和simple-youtube-api两个库,大版本升级后API返回结构可能有变化,导致你拿不到正确的频道ID字段。
内容的提问来源于stack exchange,提问作者TrueMB
相关产品推荐
相关产品推荐

