release() 方法仅在 WakeLock 实例存在且未被提前释放时才真正生效,需先判空再 await 调用,并在 visibilitychange 和 pagehide 事件中双重兜底释放。

Screen Wake Lock 的 release() 方法什么时候才真正生效
调用 release() 不等于立刻锁屏——它只是向浏览器发出“可以释放”的请求,实际是否释放取决于当前 Wake Lock 是否仍被其他条件持有(比如页面还有另一个 active 的 screen lock,或系统策略未允许)。只有当该锁是唯一活跃的、且页面处于可见/前台状态时,release() 才会同步解除锁屏。
常见误判:在 visibilitychange 事件中直接调用 release(),但没检查 document.visibilityState === 'hidden' 且锁对象存在,结果报错 TypeError: Cannot read property 'release' of null。
- 务必先判断锁对象是否已获取(非
null)且未被提前released - 推荐在
visibilitychange和pagehide双事件中处理释放,后者更可靠(尤其在 iOS Safari 中) - 不要依赖
release()的返回值做逻辑分支——它始终返回Promise<void></void>,失败时才 reject
如何安全调用 release() 并捕获可能的失败
release() 是异步方法,失败通常源于权限丢失(如用户手动关闭权限)、页面进入后台过早、或锁已被自动释放。不 await 或不 catch 会导致静默失败,屏幕持续亮着却无提示。
let wakeLock = null;
async function requestWakeLock() {
try {
wakeLock = await navigator.wakeLock.request('screen');
} catch (err) {
console.warn('Wake Lock rejected:', err.name);
}
}
async function releaseWakeLock() {
if (!wakeLock) return;
try {
await wakeLock.release(); // 必须 await,否则无法感知失败
wakeLock = null;
} catch (err) {
// 常见 err.name:'InvalidStateError'(已释放)、'NotAllowedError'(权限失效)
console.debug('Failed to release wake lock:', err.name);
}
}
- 释放前检查
wakeLock !== null,避免重复调用或空指针 - 必须
await并catch,不能只写wakeLock.release().catch(...)—— 同步阶段就可能抛出异常(如锁已无效) - 释放后立即将
wakeLock置为null,防止后续误用
在播放暂停、表单提交、用户离开等业务条件下主动释放
业务逻辑触发释放时,关键不是“能不能调”,而是“该不该还持有”。例如视频暂停后继续持锁,既耗电又违背用户预期;表单提交成功跳转前不释放,可能导致新页面锁不住(因旧锁未清)。
立即学习“前端免费学习笔记(深入)”;
- 视频暂停:
videoElement.addEventListener('pause', releaseWakeLock),但需加防抖(避免 seek 时频繁触发) - 表单提交:
form.addEventListener('submit', () => { releaseWakeLock(); }, { once: true }) - 路由跳转(如使用 History API):
window.addEventListener('popstate', releaseWakeLock),配合框架的导航守卫更稳妥 - 注意:iOS Safari 对
wakeLock持有时间敏感,超过 30 秒无交互可能被强制释放,此时release()会 resolve 但实际早已失效
兼容性与降级处理:没有 release() 怎么办
部分旧版 Chrome(release()(仅支持构造时自动释放),或 navigator.wakeLock 本身未定义。硬调用会报 TypeError: Cannot read property 'release' of undefined。
正确做法是特征检测 + 回退策略:
if ('wakeLock' in navigator && typeof navigator.wakeLock.release === 'function') {
await wakeLock.release();
} else if (wakeLock && typeof wakeLock.release === 'function') {
// 兜底:某些早期实现挂载在实例上而非原型
await wakeLock.release();
} else {
// 完全不支持:可设标志位,后续逻辑跳过锁相关操作
wakeLock = null;
}
- 永远不要假设
navigator.wakeLock存在,先'wakeLock' in navigator - 不要仅检测
navigator.wakeLock是否为 object,要确认release是函数 - 降级方案不是“模拟释放”,而是停止维护锁状态,让系统自然管理


















