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

await异步函数阻塞主线程:Discord JS音乐bot播放加歌卡顿如何解决?

解决方案

第一步:修复现有异步逻辑缺陷

你当前的异步调用存在两个明显bug,会先导致逻辑错误,再放大阻塞问题:

  1. queueAddSong方法调用异步函数searchForVideo时没有加await,会导致还没拿到搜索结果就直接向队列插入了Promise对象,后续播放逻辑会直接报错。
  2. 入口文件中调用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的工作线程可以完全脱离主线程运行计算密集型任务,不会影响主线程的音频播放逻辑。

  1. 新建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);
});
  1. 修改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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 20:24:03