You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Discord.js V12中-dog命令频繁调用报错及ReferenceError问题的修复咨询

问题修复与优化方案

先解决最直接的ReferenceError问题:你在代码里用了title变量但从来没定义过!看你的逻辑,这个title应该是Reddit帖子的标题,也就是index.title——你已经拿到了index(帖子的data对象),只需要把title替换成index.title就行,同时还要调整text变量的作用域,避免后续逻辑里出现未定义的情况。

接下来一步步梳理代码里的问题并优化:

1. 修复未定义变量与重复逻辑

你的代码里有两处重复的if (index.post_hint !== 'image')判断,而且变量作用域混乱,导致text在第二个判断里可能未定义。另外,Discord.js v12里RichEmbed已经是MessageEmbed的别名,统一用MessageEmbed更规范。

修复后的核心代码:

const Discord = require('discord.js');
const https = require('https'); // 补上你缺失的https模块导入
const url = 'https://www.reddit.com/r/lookatmydog/hot/.json?limit=100';

module.exports = {
 name: 'dog',
 description: 'sends a dog!',
 execute(message, args) {
  https.get(url, (result) => {
   let body = '';
   result.on('data', (chunk) => {
    body += chunk;
   });

   result.on('end', () => {
    try { // 加try-catch处理JSON解析失败的情况
     const response = JSON.parse(body);
     // 用数组实际长度替代硬编码的99,避免数组越界
     const index = response.data.children[Math.floor(Math.random() * response.data.children.length)].data;
     const link = 'https://reddit.com' + index.permalink;
     const subRedditName = index.subreddit_name_prefixed;

     if (index.post_hint !== 'image') {
      // 非图片帖子处理逻辑
      const text = index.selftext || 'No description provided.'; // 加默认值避免空文本
      const textEmbed = new Discord.MessageEmbed()
       .setTitle(subRedditName)
       .setColor('RANDOM')
       .setDescription(`[${index.title}](${link})\n\n${text}`) // 替换为index.title
       .setURL(`https://reddit.com/${subRedditName}`);
      return message.channel.send(textEmbed); // 用return终止后续逻辑,避免重复发送
     }

     // 图片帖子处理逻辑
     const image = index.preview.images[0].source.url.replace('&', '&');
     const imageEmbed = new Discord.MessageEmbed()
      .setTitle('Here is a dog, how nice!')
      .setImage(image)
      .setColor('RANDOM');
     message.channel.send(imageEmbed);
    } catch (err) {
     console.error('Error parsing Reddit response:', err);
     message.channel.send('Oops, something went wrong fetching a dog!');
    }
   }).on('error', function (e) {
    console.error('HTTP Request Error:', e);
    message.channel.send('Failed to fetch dog images. Try again later!');
   });
  });
 },
};

这里做了这些关键优化:

  • 补上缺失的https模块导入
  • 用response.data.children.length替代硬编码的99,防止数组越界
  • 给text加默认值,避免帖子无描述时出现空内容
  • 用return终止非图片帖子的后续逻辑,避免同时发送文本和图片embed
  • 增加try-catch处理JSON解析失败的异常
  • 统一使用MessageEmbed,移除过时的RichEmbed
  • 修复title未定义的核心错误

2. 解决频繁调用的异常问题

频繁调用时出现的错误,主要来自两个方面:

原因1:Reddit API限流

Reddit对未认证的API请求有限流规则,短时间内大量请求会被拒绝,导致请求失败进而引发后续错误。

解决方案:缓存帖子列表
不用每次调用都请求Reddit,把请求到的帖子列表缓存起来,比如5分钟内复用同一批数据:

// 模块顶部添加缓存变量
let cachedPosts = [];
let cacheExpiry = 0;

// 把发送embed的逻辑抽成单独函数
function sendDogEmbed(message, posts) {
 const index = posts[Math.floor(Math.random() * posts.length)];
 const link = 'https://reddit.com' + index.permalink;
 const subRedditName = index.subreddit_name_prefixed;

 if (index.post_hint !== 'image') {
  const text = index.selftext || 'No description provided.';
  const textEmbed = new Discord.MessageEmbed()
   .setTitle(subRedditName)
   .setColor('RANDOM')
   .setDescription(`[${index.title}](${link})\n\n${text}`)
   .setURL(`https://reddit.com/${subRedditName}`);
  return message.channel.send(textEmbed);
 }

 const image = index.preview.images[0].source.url.replace('&', '&');
 const imageEmbed = new Discord.MessageEmbed()
  .setTitle('Here is a dog, how nice!')
  .setImage(image)
  .setColor('RANDOM');
 message.channel.send(imageEmbed);
}

// 修改execute函数的请求逻辑
execute(message, args) {
 const now = Date.now();
 // 缓存未过期且有数据时直接复用
 if (now < cacheExpiry && cachedPosts.length > 0) {
  sendDogEmbed(message, cachedPosts);
  return;
 }

 // 缓存过期时发起新请求
 https.get(url, (result) => {
  let body = '';
  result.on('data', (chunk) => {
   body += chunk;
  });

  result.on('end', () => {
   try {
    const response = JSON.parse(body);
    cachedPosts = response.data.children.map(child => child.data); // 缓存所有帖子数据
    cacheExpiry = now + 5 * 60 * 1000; // 缓存5分钟
    sendDogEmbed(message, cachedPosts);
   } catch (err) {
    console.error('Error parsing Reddit response:', err);
    message.channel.send('Oops, something went wrong fetching a dog!');
   }
  }).on('error', function (e) {
   console.error('HTTP Request Error:', e);
   message.channel.send('Failed to fetch dog images. Try again later!');
  });
 });
}

原因2:Discord发送频率限制

Discord机器人短时间内发送大量消息会被限流,导致消息发送失败。

解决方案:添加命令冷却
用一个Map记录每个用户的最后调用时间,限制每5秒只能调用一次:

// 模块顶部添加冷却记录
const cooldowns = new Map();

// 在execute函数开头添加冷却逻辑
execute(message, args) {
 const userId = message.author.id;
 const cooldownTime = 5000; // 5秒冷却时间

 if (cooldowns.has(userId)) {
  const remaining = (cooldowns.get(userId) + cooldownTime - Date.now()) / 1000;
  return message.reply(`Wait ${remaining.toFixed(1)} seconds before using this command again!`);
 }

 cooldowns.set(userId, Date.now());
 setTimeout(() => cooldowns.delete(userId), cooldownTime);

 // ... 后续的缓存/请求逻辑 ...
}

3. 其他优化建议

  • 可以用node-fetch替代原生https模块,代码会更简洁易读(需要先安装npm install node-fetch)
  • 给embed添加作者信息或footer,提升用户体验
  • 增加对帖子无preview字段的判断,避免出现新的报错

内容的提问来源于stack exchange,提问作者Blake ツ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 13:04:08