如何实现playSound函数多次调用时音频序列按顺序播放
解决音频序列排队播放问题
要实现多次调用playSound时,后续的音频序列等待前一个完成再播放,核心是用任务队列+Promise管理播放流程,避免并发执行。
改造方案
- 用队列存储待执行的播放任务,每次调用
playSound时将任务加入队列 - 用Promise封装单个音频的播放逻辑,确保每个音频序列内部按顺序执行
- 维护播放状态标记,当前任务完成后自动启动下一个队列任务
完整代码实现
// 存储待执行的音频序列任务队列 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
相关产品推荐
相关产品推荐

