discord.js音乐机器人dispatcher.on("finish")多次触发清空队列问题
问题根因
你遇到的异常是由finish事件监听器重复绑定导致的:
每次调用playF函数时,无论是否创建了新的播放实例,你都会给当前的server.dispatcher追加一个新的finish事件回调。队列里加N首歌就会调用N次playF,对应绑定N个完全相同的回调函数。当第一首歌播放完成触发finish事件时,所有绑定的回调会同时执行,就会出现你观察到的:触发次数等于队列歌曲总数、队列被快速清空、机器人直接断开连接的问题。
修复方案
核心修复:仅在创建新播放实例时绑定一次事件
把finish事件的绑定逻辑移动到if(!playingMusic)的判断块内部,保证只有新生成dispatcher的时候才会绑定一次事件,不会重复追加监听器。
修复后代码如下:
function playF(connectionF, message){ console.log("starting the play function "); var server = servers[message.guild.id]; if(!playingMusic){ console.log("not playing music, running this logic "); server.dispatcher = connectionF.play(ytdl(server.queue[0], {filter: "audioonly"})); server.queue.shift(); playingMusic = true; // 事件绑定移到此处,仅创建新dispatcher时执行一次 server.dispatcher.on("finish", () => { console.log("running the finish logic "); console.log("heres your queue length in finish " + server.queue.length); playingMusic = false; if(server.queue[0]){ playF(connectionF, message); } else { connectionF.disconnect(); } }); } }
额外优化建议
如果你需要保证绝对不会出现残留监听器,可以在绑定事件前先清理该dispatcher上已有的finish监听器,加上一行server.dispatcher.removeAllListeners("finish")即可。
另外你当前用的全局playingMusic变量会导致多服务器同时使用机器人时状态冲突,建议把播放状态也存储到每个server对象中,不要用全局变量管理。
内容的提问来源于stack exchange,提问作者ElloWorld
相关产品推荐
相关产品推荐

