Node.js中基于snoostorm/snoowrap的Reddit机器人错误处理问题
解决snoostorm+snoowrap Reddit机器人的错误处理问题
你的核心问题是异步操作的错误没有被正确捕获——comment.reply()返回的是Promise,属于异步操作,你原来的try/catch只能捕获同步代码的错误,无法捕获Promise的reject抛出的错误。以下是两种可行的解决方式:
方法1:使用async/await结合try/catch
把回调函数改成async函数,用await等待comment.reply()完成,这样异步错误就能被try/catch捕获:
const r = new Snoowrap({ clientId: process.env.CLIENT_ID, clientSecret: process.env.CLIENT_SECRET, username: process.env.REDDIT_USER, password: process.env.REDDIT_PASS }); const stream = new CommentStream(r, { subreddit: 'testingground4bots', results: 1 }); stream.on('item', async comment => { try { await comment.reply('This is a test'); } catch (e) { console.error('回复出错:', e); // 根据错误类型做针对性处理 if (e.message.includes('SOMETHING_IS_BROKEN')) { console.log('该用户已屏蔽机器人'); } else if (e.message.includes('RATELIMIT')) { console.log('触发Reddit限流,需暂停操作'); } else if (e.message.includes('THREAD_LOCKED')) { console.log('目标帖子已锁定,无法回复'); } } });
方法2:直接使用Promise的.catch()方法
对comment.reply()返回的Promise调用.catch(),直接捕获异步错误:
stream.on('item', comment => { comment.reply('This is a test') .catch(e => { console.error('回复出错:', e); // 分类处理不同错误 switch (true) { case e.message.includes('SOMETHING_IS_BROKEN'): console.log('用户屏蔽了机器人'); break; case e.message.includes('RATELIMIT'): console.log('限流触发,稍后重试'); break; case e.message.includes('THREAD_LOCKED'): console.log('帖子已锁定'); break; default: console.log('其他错误:', e); } }); });
为什么原来的代码无效?
你之前尝试的try/catch只包裹了comment.reply()的调用过程(这是同步的),但reply()内部的异步网络请求错误会在Promise的reject中抛出,不会进入同步的try/catch。而你调用comment.catch()报错,是因为comment是snoowrap的Comment对象,不是Promise——只有comment.reply()的返回值才是Promise,必须对这个返回值调用.catch()。
额外:全局捕获未处理的Promise错误
如果担心有遗漏的错误,可以监听Node.js的unhandledRejection事件,避免控制台出现Unhandled rejection提示:
process.on('unhandledRejection', (reason, promise) => { console.error('未处理的Promise拒绝:', reason); // 这里可以添加全局错误日志、告警等逻辑 });
关于你提到的snoostorm开发者回复,目前该库确实没有在Stream层统一处理错误,但通过上述方法,你可以在每个异步操作的层面捕获并处理所有类型的错误(包括网络错误和Reddit平台错误),无需依赖库的更新。
内容的提问来源于stack exchange,提问作者ornato_t
相关产品推荐
相关产品推荐

