添加音频重新加载功能

This commit is contained in:
kron
2025-12-29 11:53:19 +08:00
parent 919b06bba0
commit e120ec8e7e
3 changed files with 101 additions and 37 deletions

View File

@@ -126,6 +126,8 @@ class AudioManager {
this.readyMap = new Map();
// 新增:首轮失败的音频集合与重试阶段标识
this.failedLoadKeys = new Set();
// 加载代数,用于 reloadAll 时作废旧的加载循环
this.loadGeneration = 0;
this.initAudios();
}
@@ -141,9 +143,15 @@ class AudioManager {
this.currentLoadingIndex = 0;
this.failedLoadKeys.clear();
// 增加代数,使得旧的加载循环失效
this.loadGeneration = (this.loadGeneration || 0) + 1;
const currentGen = this.loadGeneration;
this.loadingPromise = new Promise((resolve) => {
const finalize = () => {
if (currentGen !== this.loadGeneration) return;
const runRounds = (round) => {
if (currentGen !== this.loadGeneration) return;
// 达到最大轮次或没有失败项,收尾
if (this.failedLoadKeys.size === 0 || round > this.maxRetryRounds) {
this.isLoading = false;
@@ -155,30 +163,40 @@ class AudioManager {
this.failedLoadKeys.clear();
debugLog(`开始第 ${round} 轮串行加载,共 ${retryKeys.length}`);
this.loadKeysSequentially(retryKeys, () => {
// 如仍有失败项,继续下一轮;否则结束
if (this.failedLoadKeys.size > 0 && round < this.maxRetryRounds) {
setTimeout(() => runRounds(round + 1), this.retryRoundIntervalMs);
} else {
this.isLoading = false;
resolve();
}
});
this.loadKeysSequentially(
retryKeys,
() => {
if (currentGen !== this.loadGeneration) return;
// 如仍有失败项,继续下一轮;否则结束
if (this.failedLoadKeys.size > 0 && round < this.maxRetryRounds) {
setTimeout(
() => runRounds(round + 1),
this.retryRoundIntervalMs
);
} else {
this.isLoading = false;
resolve();
}
},
currentGen
);
};
// 启动第 1 轮重试(如有失败项)
runRounds(1);
};
this.loadNextAudio(finalize);
this.loadNextAudio(finalize, currentGen);
});
return this.loadingPromise;
}
// 按自定义列表串行加载音频(避免并发过多)
loadKeysSequentially(keys, onComplete) {
loadKeysSequentially(keys, onComplete, gen) {
if (gen !== undefined && gen !== this.loadGeneration) return;
let idx = 0;
const list = Array.from(keys);
const next = () => {
if (gen !== undefined && gen !== this.loadGeneration) return;
if (idx >= list.length) {
if (onComplete) onComplete();
return;
@@ -206,7 +224,8 @@ class AudioManager {
}
// 串行加载下一个音频(首轮)
loadNextAudio(onComplete) {
loadNextAudio(onComplete, gen) {
if (gen !== undefined && gen !== this.loadGeneration) return;
if (this.currentLoadingIndex >= this.audioKeys.length) {
debugLog("首轮加载遍历完成", this.currentLoadingIndex);
if (onComplete) onComplete();
@@ -220,7 +239,7 @@ class AudioManager {
);
this.createAudio(key, () => {
setTimeout(() => {
this.loadNextAudio(onComplete);
this.loadNextAudio(onComplete, gen);
}, 100);
});
}
@@ -530,6 +549,38 @@ class AudioManager {
}
return Number((loaded / total).toFixed(2));
}
// 手动重置并重新加载所有音频(用于卡住时恢复)
reloadAll() {
// 1. 停止所有播放
this.stopAll();
// 2. 销毁现有音频实例
for (const audio of this.audioMap.values()) {
try {
audio.destroy();
} catch (_) {}
}
this.audioMap.clear();
// 3. 重置状态
this.readyMap.clear();
this.failedLoadKeys.clear();
this.allowPlayMap.clear();
this.currentPlayingKey = null;
this.sequenceQueue = [];
this.sequenceIndex = 0;
this.isSequenceRunning = false;
// 4. 强制重置加载锁
this.isLoading = false;
this.loadingPromise = null;
this.currentLoadingIndex = 0;
// 5. 重新初始化 (initAudios 会自增 loadGeneration从而终止之前的任何异步循环)
return this.initAudios();
}
}
// 导出单例