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

如何实现playSound函数多次调用时音频序列按顺序播放

解决音频序列排队播放问题

要实现多次调用playSound时,后续的音频序列等待前一个完成再播放,核心是用任务队列+Promise管理播放流程,避免并发执行。

改造方案

  1. 用队列存储待执行的播放任务,每次调用playSound时将任务加入队列
  2. 用Promise封装单个音频的播放逻辑,确保每个音频序列内部按顺序执行
  3. 维护播放状态标记,当前任务完成后自动启动下一个队列任务

完整代码实现

// 存储待执行的音频序列任务队列
const playQueue = [];
// 标记当前是否正在播放音频
let isPlaying = false;

// 封装单个音频播放的Promise函数,播放完成后resolve
function playAudio(src) {
  return new Promise((resolve) => {
    const audio = document.createElement('audio');
    audio.src = src;
    audio.preload = 'auto';
    audio.onended = () => {
      // 播放完成后移除音频元素,避免DOM冗余
      audio.remove();
      resolve();
    };
    document.getElementById('content').appendChild(audio);
    audio.play();
  });
}

// 封装完整的音频序列播放逻辑,用async/await保证顺序
async function playSoundSequence() {
  await playAudio('ding.wav');
  await playAudio('sound/voice/number.wav');
  await playAudio('sound/voice/goToCounter.wav');
}

// 处理队列的核心函数,依次执行队列中的任务
async function processQueue() {
  if (isPlaying || playQueue.length === 0) return;
  isPlaying = true;
  // 取出队列首个任务执行
  const task = playQueue.shift();
  await task();
  isPlaying = false;
  // 递归启动下一个任务
  processQueue();
}

// 对外暴露的playSound函数
function playSound() {
  // 将音频序列任务加入队列
  playQueue.push(playSoundSequence);
  // 尝试启动队列处理
  processQueue();
}

代码说明

  • playAudio:把单个音频的播放逻辑封装为Promise,播放完成后自动清理DOM元素并触发resolve,保证后续流程能按顺序执行
  • playSoundSequence:通过async/await串联三个音频的播放,确保单个调用内的音频序列是依次播放的
  • playQueue:所有待执行的音频序列任务都会存入这里,保证调用顺序不被打乱
  • processQueue:负责按顺序执行队列任务,isPlaying标记避免同一时间启动多个任务,当前任务完成后自动触发下一个任务的执行

原代码问题分析

原代码每次调用playSound都会直接创建音频并播放,没有任何等待或排队逻辑,导致多个调用的音频序列同时执行,最终出现混音。改造后所有任务进入队列按顺序执行,彻底解决混音问题。

内容的提问来源于stack exchange,提问作者Alexander

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 12:15:41