Express抓取RSS存MongoDB时触发insertMany缓冲超时错误
错误原因
- 核心问题是执行RSS写入逻辑时,Mongoose还没完成MongoDB连接建立,所有数据库操作被暂存在内部缓冲队列,等待10秒没被发送到数据库就触发
buffering timed out报错。你看到的文档_id是Mongoose在本地缓冲阶段生成的,不是MongoDB服务端返回的,因此数据不会实际持久化。后台手动创建帖子功能正常,是因为人工操作时服务已经启动完成,数据库连接早已就绪。 - 逻辑写法错误:
insertMany被放在forEach循环内部,每遍历一条RSS条目就执行一次批量插入,相当于第1次插1条、第2次插2条、第3次插3条,短时间内发起N次重复写入请求,直接把缓冲队列堵死。 - 代码语法错误:重复声明两次
axios,且误将RSS接口请求返回的response对象当成后端路由的响应对象调用response.json(),该对象不存在这个方法会触发额外异常。 - 所有异步Promise都没有统一错误捕获,异常直接抛到全局触发大量UnhandledPromiseRejection警告。
修复方案
- 执行RSS抓取逻辑前,显式等待Mongoose数据库连接建立完成,再启动后续流程
- 调整写入逻辑:先遍历完所有RSS条目,把全部待插入数据整理到数组后,只调用一次
insertMany - 增加去重校验:插入前根据帖子url判断内容是否已存在,避免重复写入
- 给所有异步操作加错误捕获,不要混淆第三方接口响应对象和自身服务的路由响应对象
- 如果是独立运行的抓取脚本,操作完成后主动关闭数据库连接,避免进程挂起
修正后代码(独立脚本版本)
const mongoose = require('mongoose'); const axios = require('axios'); const { FeedItem } = require('./models/feeditem'); // 替换为实际的MongoDB连接地址 const MONGO_URI = 'mongodb://localhost:27017/你的数据库名'; const TARGET_FEED_URL = 'https://zyjswiadomie.eu/feed'; const RSS_API_ADDRESS = `https://api.rssapi.net/v1/83ad97e138f1d43536d5d0660da98095/get?url=${TARGET_FEED_URL}`; async function startRssCrawl() { try { // 等待数据库连接完成再执行后续操作 await mongoose.connect(MONGO_URI); console.log('MongoDB连接就绪'); // 拉取RSS源数据 const { data: rssResponse } = await axios.get(RSS_API_ADDRESS); const waitToInsert = rssResponse.result.entries.map(item => ({ title: item.title, text: item.description, url: item.link, })); // 过滤已存在的帖子,避免重复插入 const existedPostUrls = (await FeedItem.find( { url: { $in: waitToInsert.map(item => item.url) } }, 'url' )).map(item => item.url); const finalInsertList = waitToInsert.filter(item => !existedPostUrls.includes(item.url)); let insertResult = []; if (finalInsertList.length > 0) { insertResult = await FeedItem.insertMany(finalInsertList); console.log(`抓取完成,成功插入${insertResult.length}条新帖子`); } else { console.log('本次抓取无新内容,无需写入'); } await mongoose.disconnect(); return insertResult; } catch (error) { console.error('RSS抓取写入失败:', error); await mongoose.disconnect(); process.exit(1); } } startRssCrawl();
如果这段逻辑是写在Express等web服务的路由中,不需要手动执行数据库连接/断开操作(服务启动时已经完成连接),只需要修正循环内重复调用
insertMany、错误调用response.json()的问题即可,记得给所有异步操作添加catch捕获异常。
内容的提问来源于stack exchange,提问作者Maciej Urmański
相关产品推荐
相关产品推荐

