在之前的博客中,我们通过promise延迟对音频资源的访问,给其足够的加载时间,但是由于资源大小的不确定,5s的等待时间对于大部分较短音频来说太长了;而对于部分较长回答,5s也不足以加载完成,笨人不想做分块,所以想通过轮询访问来动态调整加载时间,优化访问速度
方案核心设计
- 智能轮询机制
- 使用递归 Promise 实现自动重试
- 指数退避策略避免服务器过载
- 最大尝试次数限制防止无限循环
- 双层检测优化

- 自适应策略
- 初始延迟:1秒(小资源快速响应)
- 指数退避:每次失败等待时间加倍(最大到30秒)
- 智能判断:针对404错误特殊处理,其他错误保持短间隔
- 错误处理增强
- 区分临时错误和永久错误
- 详细日志记录每次尝试状态
- 最终聚合错误信息
最终实现如下
javascript
function smartResourceLoader(url, maxAttempts = 10, initialDelay = 1000) {
return new Promise(async (resolve, reject) => {
let attempt = 0;
let delayTime = initialDelay;
const attemptLoad = async () => {
attempt++;
try {
console.log(`尝试加载资源 (第 ${attempt} 次): ${url}`);
// 先检查资源是否存在(使用HEAD请求减少带宽消耗)
const headRes = await Taro.request({
url,
method: 'HEAD',
timeout: 3000
});
if (headRes.statusCode === 404) {
throw new Error('资源尚未就绪 (404)');
}
// 资源存在时才执行完整操作
handleAudioToggle(url);
console.log(`资源加载成功: ${url}`);
resolve();
} catch (error) {
console.warn(`资源加载失败: ${error.message}`);
// 指数退避策略:每次失败后等待时间加倍
delayTime *= 2;
if (attempt >= maxAttempts) {
reject(new Error(`资源加载失败,超过最大尝试次数 (${maxAttempts}次)`));
return;
}
// 智能等待:根据错误类型调整策略
const nextDelay = error.message.includes('404') ? delayTime : 1000;
console.log(`等待 ${nextDelay}ms 后重试...`);
await new Promise(res => setTimeout(res, nextDelay));
attemptLoad();
}
};
attemptLoad();
});
}
