Screen Wake Lock API 仅部分支持:Chrome 84+、Edge 84+、Firefox 101+ 支持,Safari 完全不支持;需检测 "wakeLock" in navigator 再调用,Android WebView 可能返回 undefined;必须在用户手势后立即调用,否则拒绝;需手动释放并监听 visibilitychange 和 pagehide;request() 成功不代表生效,应结合 visibilityState 验证。

Screen Wake Lock API 不支持所有浏览器
Chrome 84+、Edge 84+ 和 Firefox 101+ 支持 navigator.wakeLock.request(),但 Safari 完全不支持(截至 iOS 17 / macOS 14),调用会直接抛出 TypeError: wakeLock is undefined。不能只靠 try/catch 静默吞错——得先检测可用性:
- 检查
"wakeLock" in navigator再调用,否则在 Safari 或旧版 Chrome 中会报错中断逻辑 - 即使检测通过,部分 Android WebView(如微信内置浏览器)也返回
undefined,需 fallback 到心跳式页面可见性检测 + 全屏播放空音频等 hack 方案(不推荐,仅应急) - Android 上若设备处于省电模式,系统可能无视 Wake Lock 请求,此时
request()仍成功,但屏幕仍会熄灭
request() 必须在用户手势后立即调用
navigator.wakeLock.request() 是一个需要“用户激活”(user activation)的异步操作,不能在页面加载完成、定时器或后台任务中触发,否则会拒绝并抛出 NotAllowedError。常见错误写法:
document.addEventListener("DOMContentLoaded", () => {
// ❌ 错误:没有用户手势上下文
navigator.wakeLock.request("screen").catch(console.error);
});
正确做法是绑定到显式交互事件:
- 只在
click、touchstart(非 passive)、keydown等可触发 user activation 的事件回调中调用 - 建议加一次性的
once: true防止重复请求(多次 request 同一类型会 resolve 新的WakeLockSentinel,旧的自动释放) - 不要在
setTimeout延迟后调用,哪怕只延 1ms,也会丢失激活状态
必须手动释放,且需处理页面隐藏/卸载场景
Wake Lock 不会随页面关闭自动释放,忘记 .release() 会导致用户离开后屏幕仍常亮,耗电严重。关键点:
立即学习“前端免费学习笔记(深入)”;
- 拿到
WakeLockSentinel实例后,务必保存引用,例如:let wakeLock = null; - 监听
visibilitychange:当document.hidden === true时应立即wakeLock?.release() - 监听
pagehide(比beforeunload更可靠,兼容缓存页面)做兜底释放 - 不要依赖
blur或focusout,它们不反映页面可见性,且无法捕获 PWA 后台切换
request() 返回 Promise,但失败不总是抛异常
虽然文档说失败会 reject,但实际中某些系统限制(如电源管理策略)可能导致 request("screen") resolve 成功,却无实际效果。验证是否生效更可靠的方式是:
- 结合
document.visibilityState监控:若页面未隐藏但屏幕已黑,说明 lock 失效 - 避免链式调用
.then().catch()就认为“已稳”,应在then中设置一个定时器,每 30 秒检查一次document.hidden是否意外变为true - 注意参数只能是
"screen"(目前唯一支持类型),传"system"或其他值会直接 reject
复杂点在于:它不是开关式 API,而是一组受系统策略层层过滤的请求通道。用户看到“常亮”,背后是浏览器、WebView、OS 电源管理、厂商定制 ROM 四层博弈的结果。


















