全屏API状态切换是异步的:requestFullscreen()同步发起但状态更新延至下一轮事件循环,需监听fullscreenchange事件获取最终状态,不可立即读取document.fullscreenElement。

全屏 API 的状态切换(如 requestFullscreen() 或 exitFullscreen())本身是同步发起的,但实际的全屏状态变更(如 DOM 结构更新、fullscreenchange 事件触发)会被推迟到当前 JavaScript 执行栈清空后,由事件循环在下一个宏任务阶段处理。
全屏操作不会立即改变 document.fullscreenElement
调用 element.requestFullscreen() 后,document.fullscreenElement 在同一轮 JS 执行中仍为 null(或旧值)。浏览器需先完成样式重排、渲染上下文切换等底层工作,这些不发生在 JS 线程内。状态真正更新要等到事件循环进入下一轮 —— 通常在当前同步代码执行完毕后。
- ✅ 正确做法:监听
fullscreenchange事件获取最终状态 - ❌ 错误做法:调用后立刻读取
document.fullscreenElement判断是否成功 - ⚠️ 注意:若调用被拒绝(如非用户手势触发),不会触发事件,且无异常抛出,需检查
Promise拒绝(现代浏览器返回 Promise)
现代全屏 API 返回 Promise,其 resolve 时机由事件循环调度
Chrome 71+、Firefox 69+ 等已将 requestFullscreen() 改为返回 Promise。该 Promise 在全屏切换**准备就绪并提交给渲染管线后** resolve,但仍早于 fullscreenchange 事件。这个 resolve 属于微任务(microtask),会在当前同步脚本结束、但在 fullscreenchange 这类宏任务事件之前执行。
- ✅ 可在
.then()中安全做“请求已接受”的逻辑(如禁用按钮) - ❌ 不可在
.then()中假设document.fullscreenElement已更新 —— 它大概率还没变 - ✅ 最终状态确认必须依赖
fullscreenchange事件回调
fullscreenchange 是宏任务事件,排队等待事件循环空闲
当浏览器完成全屏切换的渲染准备工作(如窗口重置、焦点调整、样式应用),它会向事件循环的任务队列中插入一个宏任务来派发 fullscreenchange。这意味着:
立即学习“Java免费学习笔记(深入)”;
- 该事件总在当前 JS 调用栈完全清空后触发(即使你刚调用完
requestFullscreen()) - 它和
setTimeout(fn, 0)、用户点击、网络响应等同属宏任务,遵循先进先出顺序 - 若你在事件处理器中又调用了
exitFullscreen(),同样会触发新一轮异步状态更新流程
实用建议:写可靠全屏状态管理的三步法
结合事件循环特性,推荐这样组织代码:
- 用
element.requestFullscreen().then(...)处理请求被接受的反馈(如 UI 加载态) - 始终用全局
document.addEventListener('fullscreenchange', ...)监听真实状态落地,并在此更新document.fullscreenElement相关逻辑 - 退出时优先用
document.exitFullscreen()(也返回 Promise),避免直接操作document.fullscreenElement


















