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

Discord.js调用栈溢出错误:/ping命令执行异常求助

问题:执行Discord /ping 命令触发调用栈溢出错误

执行/ping命令时出现以下报错:

C:\Users\Erenay\Desktop\bot\node_modules\discord.js\src\util\Util.js:21

.filter(key => !key.startsWith('_'))
^

RangeError: Maximum call stack size exceeded
at Array.filter ()
at flatten (C:\Users\Erenay\Desktop\bot\node_modules\discord.js\src\util\Util.js:21:6)
at flatten (C:\Users\Erenay\Desktop\bot\node_modules\discord.js\src\util\Util.js:48:58)
...(flatten函数重复调用,直至栈溢出)

原因分析

  • Canvas对象循环引用:chart.js生成的Chart实例会绑定到Canvas上下文上,你直接导出全局Canvas对象给ping.js使用。Discord.js序列化AttachmentBuilder时会递归遍历Canvas属性,触发循环引用,导致调用栈溢出。
  • 数据库数据处理异常:当数据库中无"Ping"数据时,默认值设为{},后续访问uptimeLinks[0].label会读取undefined的属性,虽然不是当前报错直接原因,但会导致图表初始化失败,引发连锁问题。
  • 异步操作未正确等待:wait(5000)未加await,会在图表文件写入完成前就执行删除操作,同时也可能干扰Discord.js的响应流程。

解决方案

1. 避免导出全局Canvas对象

修改/commands/ping.js,直接读取生成的本地文件作为附件,不再使用Canvas流:

const {
  EmbedBuilder,
  SlashCommandBuilder,
  AttachmentBuilder
} = require('discord.js')
const { updatePingChart } = require("../helpers/chart"); // 移除canvas导入

function wait(time) {
  return new Promise(resolve => setTimeout(resolve, time));
}
const fs = require("fs")
module.exports = {
  slash: true,
  cooldown: 1200,

  data: new SlashCommandBuilder()
    .setName('ping')
    .setDescription('Shows bot ping.'),

  async execute(client, interaction) {
    let pinge = '<:Bot:1065675104027148338>'
    let bote = '<:Ping:1065675122683412481>'
    let messageping = new Date().getTime() - interaction.createdTimestamp
    let ping = client.ws.ping // client.ws.ping不是异步操作,无需await
    
    await updatePingChart(ping)
    
    // 直接读取生成的本地文件
    const attachment = new AttachmentBuilder('pingChart.png', {
      name: 'ping.png'
    });
    
    const embed = new EmbedBuilder()
      .addFields({
        name: `${bote} **Bot ping:**`,
        value: `\`${ping}ms\``
      }, {
        name: `${pinge} **Message ping:**`,
        value: `\`${messageping}ms\``
      })
      .setColor(`Gold`)
      
    await interaction.reply({
      embeds: [embed],
      attachments: [attachment]
    })
    
    await wait(5000) // 添加await,等待文件写入完成再删除
    fs.unlinkSync('pingChart.png');
  }
}

2. 修复数据库数据处理逻辑

修改/helpers/chart.js,确保数据格式正确,添加ping数据记录逻辑:

const db = require("croxydb")
const { createCanvas } = require("canvas")
const width2 = 800;
const height2 = 400;
const Chart = require("chart.js/auto")

const fs = require("fs")
let myChart;

async function updatePingChart(pingValue) {
  if (myChart) {
    myChart.destroy();
  }

  // 设默认值为空数组,而非空对象
  let uptimeLinks = db.get("Ping") || [];
  // 初始化数据结构
  if (!uptimeLinks.length) {
    uptimeLinks = [{ label: [], ping: [] }];
  }
  let labels = uptimeLinks[0].label;
  let pinkg = uptimeLinks[0].ping;
  
  // 添加当前ping记录,限制历史数据长度(最多20条)
  const currentTime = new Date().toLocaleTimeString();
  labels.push(currentTime);
  pinkg.push(pingValue);
  if (labels.length > 20) {
    labels.shift();
    pinkg.shift();
  }
  // 更新数据库
  db.set("Ping", uptimeLinks);
  
  const canvas = createCanvas(width2, height2); // 每次创建新Canvas,避免全局对象污染
  const ctx2 = canvas.getContext('2d');

  const configuration = {
    type: 'line',
    data: {
      labels: labels,
      datasets: [{
        label: 'Ping (ms)',
        backgroundColor: 'rgba(75, 192, 192, 0.2)',
        borderColor: 'rgba(75, 192, 192, 1)',
        data: pinkg,
        yAxisID: 'y-axis-1',
      }]
    },
    options: {
      scales: {
        x: { // 去掉数组包裹,Chart.js scale配置无需数组
          type: 'category', // 改为分类轴,适配时间标签
          position: 'bottom',
          ticks: {
            callback: function(value, index) {
              // 调整标签显示间隔,避免拥挤
              if (index % 4 === 0 && labels[index]) {
                return labels[index];
              } else {
                return '';
              }
            }
          }
        },
        y: [{
            type: 'linear',
            display: true,
            position: 'left',
            id: 'y-axis-1',
          },
          {
            type: 'linear',
            display: true,
            position: 'right',
            id: 'y-axis-2',
            ticks: {
              max: 1,
              min: 0,
              stepSize: 1,
              callback: function(value) {
                return value === 1 ? 'Up' : 'Down';
              }
            }
          },
        ]
      }
    }
  };

  myChart = new Chart(ctx2, configuration);

  const out = fs.createWriteStream('pingChart.png');
  const stream = canvas.createPNGStream();

  return new Promise((resolve, reject) => {
    stream.pipe(out);
    out.on('finish', () => {
      resolve('The chart image was saved.');
    });
    out.on('error', (err) => {
      reject(err);
    });
  });
}

module.exports = {
  updatePingChart: updatePingChart
}; // 不再导出canvas对象

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 09:13:10