0

0

解决移动设备上通过AJAX播放音频的NotAllowedError

聖光之護

聖光之護

发布时间:2025-11-05 21:09:18

|

467人浏览过

|

来源于php中文网

原创

解决移动设备上通过ajax播放音频的notallowederror

本文旨在解决移动设备上通过AJAX动态加载音频时遇到的`NotAllowedError`,特别是当`onerror`事件未能触发的问题。核心在于理解移动浏览器对用户手势的严格要求,并指出传统的`click`事件在触摸设备上可能无法满足这些要求,推荐使用更符合触摸交互的`touchend`事件来确保音频播放的成功。

理解移动设备上的音频播放限制与NotAllowedError

在开发Web应用时,尤其是在移动设备上,尝试通过JavaScript动态播放音频常常会遇到NotAllowedError。这种错误通常表现为控制台输出Uncaught (in promise) NotAllowedError,并且令人困惑的是,标准的audio.onerror事件可能并不会被触发。

这个问题的根源在于现代浏览器,特别是移动浏览器,为了改善用户体验和防止滥用,对媒体(包括音频和视频)的自动播放实施了严格的策略。这些策略通常要求媒体播放必须由明确的用户手势(User Gesture)触发。当代码尝试在没有足够用户手势的情况下播放音频时,浏览器会阻止播放并抛出NotAllowedError。

原始场景中,用户点击按钮触发AJAX请求,获取音频路径后赋值给

解决策略:利用触摸事件确保用户手势有效性

针对移动设备上的这种问题,关键在于确保触发audio.play()的代码确实是在一个被浏览器认为是“有效用户手势”的上下文中执行的。对于触摸屏设备,传统的click事件在某些情况下可能表现不一致或不被视为足够强烈的用户手势。此时,使用更原生的触摸事件,如touchend,可以更可靠地满足浏览器的要求。

touchend事件在用户手指从屏幕上抬起时触发,它更直接地反映了触摸交互,并且在移动设备上通常被视为一个可靠的用户手势。

Digram
Digram

让Figma更好用的AI神器

下载

示例代码优化

让我们基于原始问题,优化代码以处理移动设备上的NotAllowedError。我们将重点放在错误重试机制上,确保重试按钮的点击(或触摸)能够成功触发音频播放。

HTML 结构保持不变:



JavaScript 优化:

document.addEventListener('DOMContentLoaded', function() {
    const audioPlayer = document.getElementById('audio');
    const playButton = document.getElementById('play-audio');
    const retryButton = document.getElementById('retry');

    // 辅助函数:尝试播放音频并处理Promise
    function tryPlayAudio() {
        // audioPlayer.load(); // 可以在播放前调用load(),但通常不是解决NotAllowedError的关键
        const playPromise = audioPlayer.play();

        if (playPromise !== undefined) {
            playPromise.then(() => {
                console.log('Audio is playing successfully.');
                retryButton.style.display = "none"; // 播放成功则隐藏重试按钮
            }).catch(error => {
                // NotAllowedError 会在这里被捕获
                console.error('Audio play failed:', error.name, error.message);
                if (error.name === 'NotAllowedError' || error.name === 'AbortError') {
                    // 即使onerror不触发,Promise的catch也能捕获到
                    console.log('Displaying retry button due to play error.');
                    retryButton.style.display = "block";
                }
            });
        }
    }

    // 初始播放按钮的点击事件
    playButton.addEventListener('click', function() {
        $.ajax({
            url: "../audio/audio.json", // 假设这是一个返回 { "sound": "path/to/audio.mp3" } 的JSON
            type: 'GET',
            dataType: "json",
            success: function(response) {
                audioPlayer.src = response.sound;
                // 尝试播放音频
                tryPlayAudio();
            },
            error: function(xhr, status, error) {
                console.error('Failed to fetch audio path:', status, error);
                // 可以在这里显示错误信息或重试按钮
                retryButton.style.display = "block";
            }
        });
    });

    // 关键优化:为重试按钮添加touchend事件监听
    // 对于移动设备,touchend通常比click更可靠地触发用户手势策略
    retryButton.addEventListener('touchend', function(event) {
        event.preventDefault(); // 阻止默认的触摸行为,如滚动
        console.log('Retry button touched, attempting to play audio...');
        tryPlayAudio(); // 再次尝试播放
    });

    // 也可以保留click事件作为桌面设备的备用,但touchend优先级更高
    retryButton.addEventListener('click', function() {
        // 如果touchend已经处理,这里可能不会执行或不重要
        console.log('Retry button clicked (fallback), attempting to play audio...');
        tryPlayAudio();
    });

    // 监听audio元素的错误事件(作为补充,即使它可能不总是触发NotAllowedError)
    audioPlayer.onerror = function(e) {
        console.error('Audio element onerror event fired:', e);
        // 如果这里捕获到错误,也显示重试按钮
        retryButton.style.display = "block";
    };

    audioPlayer.onplaying = function() {
        console.log('Audio is actually playing.');
    };
});

代码解释与注意事项:

  1. audio.play() 返回 Promise: 现代浏览器中,audio.play() 方法会返回一个 Promise。这是处理播放错误(包括 NotAllowedError)的推荐方式。即使 onerror 事件不触发,Promise.catch() 也能捕获到播放失败的原因。
  2. touchend 事件: 对于重试按钮,我们专门添加了 touchend 事件监听器。在移动设备上,当用户通过触摸与页面交互时,touchend 事件是浏览器最认可的用户手势之一。它能更有效地绕过自动播放限制。
  3. event.preventDefault(): 在触摸事件处理器中调用 event.preventDefault() 是一个好习惯,可以避免某些默认的触摸行为(如滚动或缩放)干扰按钮点击。
  4. DOMContentLoaded: 将所有JavaScript代码包裹在 DOMContentLoaded 事件监听器中,确保在DOM完全加载后再执行脚本,避免元素未找到的错误。
  5. 桌面兼容性: 可以保留 click 事件作为桌面设备的备用,但 touchend 在移动设备上会更早且更可靠地触发。
  6. 错误处理粒度: NotAllowedError 通常表示浏览器策略限制,而不是文件不存在或损坏。对于后者,onerror 事件可能更容易触发。通过 Promise.catch() 可以统一处理这两种情况。

总结

在移动设备上处理通过AJAX动态加载音频时的NotAllowedError,核心在于尊重并满足浏览器的用户手势策略。虽然click事件在桌面端通常足够,但在触摸设备上,使用更原生的触摸事件(如touchend)来触发音频播放,可以显著提高成功率。同时,利用audio.play()返回的Promise进行错误处理,是现代Web开发中处理媒体播放失败的健壮方法,它能捕获到onerror事件可能遗漏的NotAllowedError。通过结合这些策略,可以构建出在各种设备上都更加可靠的音频播放功能。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
ajax教程
ajax教程

php中文网为大家带来ajax教程合集,Ajax是一种用于创建快速动态网页的技术。通过在后台与服务器进行少量数据交换,Ajax可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。php中文网还为大家带来ajax的相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

159

2023.06.14

ajax中文乱码解决方法
ajax中文乱码解决方法

ajax中文乱码解决方法有设置请求头部的字符编码、在服务器端设置响应头部的字符编码和使用encodeURIComponent对中文进行编码。本专题为大家提供ajax中文乱码相关的文章、下载、课程内容,供大家免费下载体验。

160

2023.08.31

ajax传递中文乱码怎么办
ajax传递中文乱码怎么办

ajax传递中文乱码的解决办法:1、设置统一的编码方式;2、服务器端编码;3、客户端解码;4、设置HTTP响应头;5、使用JSON格式。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

117

2023.11.15

ajax网站有哪些
ajax网站有哪些

使用ajax的网站有谷歌、维基百科、脸书、纽约时报、亚马逊、stackoverflow、twitter、hacker news、shopify和basecamp等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

234

2024.09.24

DOM是什么意思
DOM是什么意思

dom的英文全称是documentobjectmodel,表示文件对象模型,是w3c组织推荐的处理可扩展置标语言的标准编程接口;dom是html文档的内存中对象表示,它提供了使用javascript与网页交互的方式。想了解更多的相关内容,可以阅读本专题下面的文章。

3303

2024.08.14

promise的用法
promise的用法

“promise” 是一种用于处理异步操作的编程概念,它可以用来表示一个异步操作的最终结果。Promise 对象有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。Promise的用法主要包括构造函数、实例方法(then、catch、finally)和状态转换。

306

2023.10.12

html文本框类型介绍
html文本框类型介绍

html文本框类型有单行文本框、密码文本框、数字文本框、日期文本框、时间文本框、文件上传文本框、多行文本框等等。详细介绍:1、单行文本框是最常见的文本框类型,用于接受单行文本输入,用户可以在文本框中输入任意文本,例如用户名、密码、电子邮件地址等;2、密码文本框用于接受密码输入,用户在输入密码时,文本框中的内容会被隐藏,以保护用户的隐私;3、数字文本框等等。

405

2023.10.12

ipad游戏没有声音
ipad游戏没有声音

ipad游戏没有声音是因为静音模式、音量设置、耳机连接、音频输出设置、游戏设置、软件更新、重启设备、硬件故障和游戏应用问题造成的。

986

2023.09.11

Python 自然语言处理(NLP)基础与实战
Python 自然语言处理(NLP)基础与实战

本专题系统讲解 Python 在自然语言处理(NLP)领域的基础方法与实战应用,涵盖文本预处理(分词、去停用词)、词性标注、命名实体识别、关键词提取、情感分析,以及常用 NLP 库(NLTK、spaCy)的核心用法。通过真实文本案例,帮助学习者掌握 使用 Python 进行文本分析与语言数据处理的完整流程,适用于内容分析、舆情监测与智能文本应用场景。

10

2026.01.27

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 4.2万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 2.5万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号