一聚教程网:一个值得你收藏的教程网站

热门教程

如何借助 Page Lifecycle API 管理网页在后台被挂起时的资源回收

时间:2026-07-27 09:57:05 编辑:袖梨 来源:一聚教程网

Page Lifecycle API 是唯一可靠捕获后台冻结或丢弃的机制;需监听 freeze 事件即时清理定时器、取消请求,并在 pagehide 且 event.persisted 为 true 时补救,document.wasDiscarded 仅用于恢复后状态重置。

移动端网页在后台被冻结(Frozen)或丢弃(Discarded)时,beforeunloadpagehide 都可能来不及触发,导致状态丢失、定时器残留、网络请求未清理。Page Lifecycle API 是目前唯一能可靠捕获这些系统级干预的机制。

监听 freeze 事件做即时资源释放

freeze 是页面进入 Frozen 阶段前的最后一个可执行 JS 的时机,此时 DOM 仍可读、定时器尚未停摆,但之后所有异步任务都会被挂起。错过它,就等于放弃主动回收机会。

  • 必须用 addEventListener('freeze', handler, { once: true }),避免重复绑定
  • 在此回调中应立即:clearInterval / clearTimeout 所有活跃定时器,取消未完成的 fetch 请求(通过 AbortController),解除 requestIdleCallback 回调
  • 不要尝试发起新网络请求或修改 DOM——浏览器可能已开始冻结流程,这些操作会被静默丢弃

区分 pagehideevent.persisted 真实含义

pagehide 事件本身不区分是用户导航离开还是系统冻结,关键看 event.persisted:为 true 表示页面可能被缓存(Back/Forward Cache 或 Frozen),为 false 则大概率是正常卸载(Terminated)。

  • event.persisted === true 且尚未触发过 freeze(比如某些 Android WebView 不发 freeze),需在此刻补做一次资源清理
  • event.persisted === false,说明页面即将彻底销毁,可跳过保存逻辑,专注释放(如清除 localStorage 临时键)
  • 注意:Safari 在部分 iOS 版本中对 persisted 返回不一致,建议配合 document.visibilityState === 'hidden' 二次校验

避免在 visibilitychange 中误判 Frozen 状态

visibilitychange 只反映可见性,不能代表是否被冻结。页面可能长期处于 visibilityState === 'hidden' 却未被冻结(如桌面多窗口切换),也可能在 visible 状态下被突然冻结(iOS Safari 某些后台场景)。

  • 不要仅靠 visibilitychange 触发 heavy cleanup,容易过早释放资源
  • 真正可靠的冻结信号只有 freeze 事件;visibilitychange 仅适合轻量操作,如暂停视频、暂停 Canvas 动画
  • 检查 document.hasFocus()document.visibilityState 组合,可辅助识别 Passive/Active 切换,但和 Frozen 无直接因果

document.wasDiscarded 只在恢复时有用

document.wasDiscarded 是一个只读布尔值,页面从 Discarded 状态恢复(即用户重新打开该标签页)后才为 true,且仅在首次 JS 执行时有效——之后刷新就变回 false

  • 它无法用于预测丢弃,只能用于“事后补救”:比如恢复前清空旧状态、重载关键数据、重置全局计数器
  • 不要把它和 freezepagehide 混用;它不触发事件,也不影响生命周期流转
  • 实际使用时,应在入口脚本最顶部检查,例如:
    if (document.wasDiscarded) { restoreFromCache(); }

Frozen 阶段没有回调机会,Discarded 更是零 JS 执行权——所以所有清理动作必须挤压在 freeze 和带 persisted === truepagehide 这两个狭窄窗口里完成。任何依赖“稍后处理”的设计,在这里都会失效。

热门栏目