discord.js v13 音乐机器人play命令queue队列调用异常问题求助
问题根源
你遇到的报错是由以下几个问题共同导致的:
- messageCreate.js中单独声明了局部
queue变量,没有复用你在index.js里挂载到client实例上的全局共享队列 - play.js中调用自定义函数
video_player时没有传入queue参数,导致该函数内部读取queue时返回undefined,调用queue.get()直接抛出类型错误 video_player函数内部直接使用了未声明的connection变量,销毁连接时会触发第二次报错
修复步骤
第一步:修改messageCreate.js,复用全局队列
删除messageCreate.js中单独声明的局部queue,直接使用client.queue,修改后代码如下:
const del = require('../../functions.js'); const Levels = require('discord-xp'); require('dotenv').config(); const prefix = process.env.PREFIX; module.exports = async (Discord, client, message) => { if (message.author.bot || !message.guild) return; const randomXP = Math.floor(Math.random() * 14) + 1; //1-15 const hasLeveledUP = await Levels.appendXp(message.author.id, message.guild.id, randomXP); if (hasLeveledUP) { const user = await Levels.fetch(message.author.id, message.guild.id); message.channel.send(`${message.member} is now level ${user.level}.`); } const args = message.content.slice(prefix.length).trim().split(" "); const cmd = args.shift().toLowerCase(); if (cmd.length === 0) return; let command = client.commands.get(cmd) || client.commands.find(c => c.aliases?.includes(cmd)); if (command) { command.run(client, message, args, client.queue); } }
第二步:修改play.js中的调用逻辑和video_player函数
- 调用
video_player时传入queue参数 - 修复
video_player内部未声明connection的问题
修改后play.js相关部分代码:
// 原try代码块部分修改 try { const connection = joinVoiceChannel({ channelId: voiceChannel.id, guildId: message.guild.id, adapterCreator: message.guild.voiceAdapterCreator }); queue_constructor.connection = connection; // 新增传入queue参数 video_player(message.guild, queue_constructor.songs[0], queue); } catch (err) { queue.delete(message.guild.id); message.channel.send('Error connecting'); throw err; } // ... 其他代码不变,修改video_player函数 const video_player = async (guild, song, queue) => { const song_queue = queue.get(guild.id); if(!song) { // 调用song_queue中存储的connection,避免使用未声明变量 song_queue.connection.destroy(); queue.delete(guild.id); return; } const audioPlayer = createAudioPlayer(); song_queue.connection.subscribe(audioPlayer); const stream = ytdl(song.url, { filter: 'audioonly' }); audioPlayer.play(createAudioResource(stream, {seek: 0, volume: 1})) audioPlayer.on(AudioPlayerStatus.Idle, () => { song_queue.songs.shift(); // 递归调用时也要传入queue参数 video_player(guild, song_queue.songs[0], queue); }); song_queue.text_channel.send(`Now playing **${song.title}**`) }
可选优化
因为队列已经全局挂载在client.queue上,你可以直接在play.js的run函数里通过client.queue访问,不需要单独传queue参数,可避免后续传参遗漏的问题。
内容的提问来源于stack exchange,提问作者clxne
相关产品推荐
相关产品推荐

