await异步函数阻塞主线程:Discord JS音乐bot播放加歌卡顿如何解决?
解决方案
第一步:修复现有异步逻辑缺陷
你当前的异步调用存在两个明显bug,会先导致逻辑错误,再放大阻塞问题:
queueAddSong方法调用异步函数searchForVideo时没有加await,会导致还没拿到搜索结果就直接向队列插入了Promise对象,后续播放逻辑会直接报错。- 入口文件中调用
client.modules.queue.add时没有加await,会导致异步逻辑顺序混乱。
先修复queueAddSong:
async function queueAddSong(msg, queue, terms, player) { // 加await等待搜索结果返回 const song = await searchForVideo(msg, terms); if (!song) return; // 搜索无结果直接返回 console.log(`Adding to queue: ${song.title}`); queue.songs.push(song); if (player.state.status === 'idle') startQueue(queue, player); }
再修复入口文件的调用:
// 原调用行改为加await await client.modules.queue.add(msg, qMap.get(msg.guildId), args, player);
第二步:解决yt-search阻塞主线程问题
yt-search会在本地做大量HTML解析、正则匹配的同步计算,直接卡住Node.js的事件循环,导致音频播放的实时任务无法执行,以下两种可选方案:
方案1:使用worker_threads把搜索逻辑放到独立线程(推荐,不需要额外申请密钥)
Node.js的工作线程可以完全脱离主线程运行计算密集型任务,不会影响主线程的音频播放逻辑。
- 新建
search.worker.js作为独立工作线程文件:
const { parentPort } = require('worker_threads'); const ytdl = require('ytdl-core'); const ytSearch = require('yt-search'); parentPort.on('message', async (query) => { let song = {}; if (ytdl.validateURL(query[0])) { const songInfo = await ytdl.getInfo(query[0]); song = { title: songInfo.videoDetails.title, url: songInfo.videoDetails.video_url }; } else { const vidResults = await ytSearch(query.join(' ')); if (vidResults.videos.length >= 1) { song = { title: vidResults.videos[0].title, url: vidResults.videos[0].url }; } else { song = null; } } parentPort.postMessage(song); });
- 修改
searchForVideo逻辑,调用工作线程处理搜索:
const { Worker } = require('worker_threads'); function searchForVideo(msg, query) { return new Promise((resolve) => { const worker = new Worker('./search.worker.js'); worker.postMessage(query); worker.on('message', (song) => { if (!song) msg.reply(':x: No results found'); resolve(song); worker.terminate(); }); }); }
方案2:替换为YouTube Data API搜索
如果不想维护工作线程,可以直接调用官方的YouTube搜索接口,整个过程只有网络IO,没有本地计算开销,完全不会阻塞主线程,只需要申请YouTube Data API v3的密钥即可。
额外优化建议
- 可以做搜索结果缓存,同一个关键词搜索过的结果直接存在本地,不需要重复调用搜索接口,减少资源消耗
- 工作线程可以做池化,不需要每次搜索都新建销毁线程,降低运行开销
内容的提问来源于stack exchange,提问作者Odobenous
相关产品推荐
相关产品推荐

