navigator.permissions.query() 是唯一合法的权限预检方式,仅支持 geolocation、notifications、microphone、camera、clipboard-read/write;state 为 granted/denied/prompt,须在用户交互中调用且注意 safari 兼容性。

navigator.permissions.query() 是唯一能预先检测权限状态的合法方式,别再用 try/catch 调用原始 API 碰运气了。它不触发弹窗、不改变状态,只读取当前浏览器记录的授权决策。
哪些权限名能被 navigator.permissions.query() 识别
不是所有功能都支持预查。目前稳定支持的只有以下几类(截至 2026 年 4 月):
-
'geolocation'(定位) -
'notifications'(通知) -
'microphone'(麦克风) -
'camera'(摄像头) -
'clipboard-read'和'clipboard-write'(剪贴板读写)
常见错误现象:navigator.permissions.query({ name: 'battery' }) 或 { name: 'usb' } 会直接 reject,报 TypeError: Permission name is not supported。这些权限尚未纳入标准,或仅限扩展/原生应用使用。
PermissionStatus.state 的三个值不是布尔开关
返回的 state 是字符串,含义和实际行为强绑定:
-
'granted':可立即调用对应 API,比如navigator.geolocation.getCurrentPosition(),不会弹窗 -
'denied':用户点过「拒绝」,或浏览器策略禁用(如无痕模式下通知默认被拒),此时再调原始 API 会直接抛NotAllowedError -
'prompt':尚未授予权限,但注意——这不保证下次调用就一定弹窗。例如在 HTTP 页面查geolocation,state永远是'prompt',但调用时直接失败,连弹窗机会都没有
性能 / 兼容性影响:Chrome、Edge、Firefox 均已完整支持;Safari 仅部分支持(geolocation 和 notifications 可查,microphone/camera 在 iOS 17.4+ 才可用)。别在 Safari 里对 microphone 做条件分支,大概率 fallback 到 undefined。
必须配合用户交互触发,否则多数浏览器会静默拒绝
即使你写了 navigator.permissions.query({ name: 'microphone' }),如果它在页面加载时自动执行(比如放在 script 标签顶层),Chrome 和 Edge 会直接返回 state: 'prompt',哪怕用户之前授过权——这是防滥用策略。
- 正确做法:只在用户明确操作后调用,比如点击「开始录音」按钮的事件回调里
- 错误写法:
window.addEventListener('load', () => navigator.permissions.query(...)) - 移动端特别注意:iOS Safari 对非用户手势触发的查询一律返回
'prompt',且不触发onchange监听
容易踩的坑:有人把查询逻辑塞进 setTimeout 延迟 100ms 就以为绕过了限制,其实没用。浏览器判断的是调用栈是否源于可信用户动作(click、keydown、touchend),不是时间戳。
真正难处理的不是怎么查,而是怎么应对 'prompt'——它既可能是“还没问”,也可能是“问了但被拦”。这时候得结合上下文做降级:比如先显示「请允许访问麦克风」文案,再等用户点击才真正发起 getUserMedia 请求。别指望一个 query 调用就能覆盖所有设备和策略差异。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











