Discord机器人执行-rig命令报Cannot read property 'id' of undefined错误如何解决
错误具体成因
- 代码结构严重错位:
rigStats异步函数仅定义了前3行逻辑,就错误插入了Discord客户端的ready、message事件监听代码,导致函数逻辑完全断裂,后续遍历矿机、给stats变量赋值的代码执行时机完全混乱。 - Nicehash客户端未初始化:仅导入了
NicehashJS依赖,未实例化生成nhClient对象,调用nhClient.getMiningRigs()时直接抛出异常,stats变量永远不会被赋值,保持初始的undefined状态。 - 无边界校验逻辑:如果传入的矿机名称
rigName不存在于Nicehash返回的矿机列表中,stats变量同样不会被赋值,后续构造Embed消息时访问stats.id直接触发Cannot read property 'id' of undefined报错。 - 无异常捕获机制:
rigStats是异步函数,内部抛出的异常没有被try/catch捕获,调用该函数时也没有添加.catch()处理,异常最终成为未处理的Promise拒绝。 - 其他语法问题:Embed的GPU字段内嵌代码块时错误直接使用三个反引号,不符合JS字符串语法;
rig变量未声明直接赋值成为隐式全局变量,可能引发不可预期的问题。
修复方案
- 调整代码结构,正确初始化Nicehash客户端,将Discord事件监听代码移到函数外部,同时补充所有异常捕获、边界校验逻辑,修复后完整参考代码如下:
const NicehashJS = require('./lib/api.js') const Discord = require('discord.js'); const axios = require('axios'); const client = new Discord.Client(); const moment = require('moment-timezone'); const botToken = '' const apiKey = '' const apiSecret = '' const organizationId = '' // 初始化Nicehash客户端 const nhClient = new NicehashJS(apiKey, apiSecret, organizationId) async function rigStats(rigName, message) { try { const rawResponse = await nhClient.getMiningRigs() const data = rawResponse.data.miningRigs let stats = null // 遍历矿机逻辑放在函数内部 for (let i in data) { if (data[i].name == rigName) { // 声明rig变量 let rig = { id: data[i].rigId, rigName: data[i].name, status: data[i].minerStatus, unpaid: data[i].unpaidAmount, profitability: parseFloat(data[i].profitability).toFixed(8), stats: [] } // 增加axios请求错误捕获 try { const resp = await axios.get('https://api.coindesk.com/v1/bpi/currentprice/myr.json') rig.profitability = { "BTC": data[i].profitability, "USD": parseFloat(data[i].profitability * resp.data.bpi.USD.rate_float).toFixed(2), "MYR": parseFloat(data[i].profitability * resp.data.bpi.MYR.rate_float).toFixed(2) } } catch(e) { return message.channel.send('获取汇率信息失败') } if (rig.status !== 'OFFLINE') { for (let x in data[i].devices) { if (data[i].devices[x].status.enumName == 'DISABLED') { rig.stats.push({ gpu: data[i].devices[x].name, status: data[i].devices[x].status.enumName, temp: '-', load: '-', power: '-', hashrate: '-', algo: '-' }) } else { rig.stats.push({ gpu: data[i].devices[x].name, status: data[i].devices[x].status.enumName, temp: parseFloat(data[i].devices[x].temperature % 65536).toFixed(0) + '°C', load: parseFloat(data[i].devices[x].load / 65536).toFixed(0) + '%', power: `${data[i].devices[x].powerUsage}W`, hashrate: parseFloat(data[i].devices[x].speeds[0].speed).toFixed(2) + data[i].devices[x].speeds[0].displaySuffix, algo: data[i].devices[x].speeds[0].algorithm }) } } } stats = rig } } // 增加矿机不存在的校验 if (!stats) { return message.channel.send('未找到对应名称的矿机') } // 构造Embed var embed = { "title": `Rig Stats`, "url": `https://www.nicehash.com/my/mining/rigs/${stats.id}`, "color": 0, "footer": { "text": moment.tz('Asia/Kuala_Lumpur').format("HH:mm:ss") + " MYT" }, "fields": [ { "name": "Rig Name", "value": `${stats.rigName}`, "inline": true }, { "name": "Rig ID", "value": `${stats.id}`, "inline": true }, { "name": "Status", "value": `${stats.status}` }, { "name": "Profitability", "value": `BTC ${parseFloat(stats.profitability.BTC).toFixed(8)}\nUSD ${parseFloat(stats.profitability.USD).toFixed(2)}\nMYR ${parseFloat(stats.profitability.MYR).toFixed(2)}` } ] } // 修复Embed代码块语法 for (let i in stats.stats) { embed.fields.push({ "name": `GPU: ${stats.stats[i].gpu}`, "value": `\`\`\`Status: ${stats.stats[i].status}\nTemperature: ${stats.stats[i].temp}\nLoad: ${stats.stats[i].load}\nPower: ${stats.stats[i].power}\nHashrate: ${stats.stats[i].hashrate}\nAlgorithm: ${stats.stats[i].algo}\`\`\``, "inline": true }) } message.channel.send({ embed }) } catch (e) { // 捕获函数内部所有异常 console.error(e) message.channel.send('获取矿机信息失败') } } // 事件监听放在函数外部 client.on('ready', () => { console.log(`Logged in as ${client.user.tag}!`); }); client.on("message", async message => { var args = message.content.substring(1).split(" "); if (message.author.bot) return; if (message.content.startsWith("-rig")) { if (!args[1]) return message.channel.send('请输入矿机名称') rigStats(args[1], message) } }) client.login(botToken)
- 可根据需要添加Node启动参数
--unhandled-rejections=strict,出现未处理的Promise拒绝时直接终止进程,方便定位问题。
内容的提问来源于stack exchange,提问作者TCV
相关产品推荐
相关产品推荐

