仅Safari浏览器执行函数时出现Promise未处理拒绝错误求助
错误成因分析与解决方案
根据你提供的错误信息和代码,这个Safari特有的NotSupportedError主要有以下几个可能的成因:
1. OGG音频格式支持不足
Safari(尤其是iOS Safari和旧版macOS Safari)对OGG音频格式的支持不完善,部分版本甚至完全不支持。这会导致设置音频src后无法加载资源,调用play()时触发「操作不支持」的错误。
2. Safari自动播放策略限制
Safari有严格的自动播放规则:非用户交互触发的音频/视频播放会被浏览器阻止。如果这段代码是在页面加载、定时器或其他非用户点击/触摸事件中执行的,play()方法返回的Promise会被拒绝,从而抛出Unhandled Promise Rejection错误。
3. 音频未完成加载就调用播放
直接设置src后立即调用play(),音频资源可能还没完成加载(尤其是网络较慢时),Safari此时会因为资源未就绪而抛出不支持操作的错误。
对应修复方案:
添加音频格式 fallback
同时提供OGG和MP3格式的音频,让浏览器自动选择支持的格式:<!-- 替换原来的单个audio标签 --> <audio id="voice"> <source src="sounds/[文件名].ogg" type="audio/ogg"> <source src="sounds/[文件名].mp3" type="audio/mpeg"> </audio>代码中动态生成音频源时,也需要同时添加两种格式的source标签。
确保播放触发自用户交互
将播放逻辑包裹在用户点击/触摸事件回调中,比如绑定到你的repeat_btn点击事件:$("#repeat_btn").on('click', function() { $(this).addClass("repeat_hover"); // 原有的post请求逻辑 if (diff_lvl == 1) { $.post('played_games.php?diff=1', {game:"voice",post_id:<?php echo $usr_id; ?>}, function (data) { $('#result').html(data); }); } else if (diff_lvl == 3) { $.post('played_games.php?diff=3', {game:"voice",post_id:<?php echo $usr_id; ?>}, function (data) { $('#result').html(data); }); } // 音频播放逻辑 var count = array_voices_hashes.length; var newpic_onload = Math.floor(Math.random() * count); var randompic_onload = array_voices_hashes[newpic_onload]; var audio = document.getElementById("voice"); // 清空原有source audio.innerHTML = ''; // 添加双格式源 var oggSource = document.createElement('source'); oggSource.src = 'sounds/' + randompic_onload + '.ogg'; oggSource.type = 'audio/ogg'; var mp3Source = document.createElement('source'); mp3Source.src = 'sounds/' + randompic_onload + '.mp3'; mp3Source.type = 'audio/mpeg'; audio.appendChild(oggSource); audio.appendChild(mp3Source); // 等待音频加载完成再播放 audio.addEventListener('canplaythrough', function playAudio() { audio.play().catch(function(err) { // 捕获播放错误,避免未处理的Promise拒绝 console.error('播放失败:', err); }); audio.removeEventListener('canplaythrough', playAudio); }); cdreset(); countdown(); });捕获play()的Promise异常
即使做了上述处理,仍需主动捕获play()返回的Promise错误,避免控制台抛出未处理的拒绝:document.getElementById("voice").play().catch(function(error) { console.error('音频播放失败:', error); // 可在此添加降级处理,比如提示用户手动点击播放 });
内容的提问来源于stack exchange,提问作者Shadowned
相关产品推荐
相关产品推荐

