discarded状态无法被JavaScript捕获,唯一线索是pageshow中persisted===false且为全新加载;可靠保存时机仅freeze事件和pagehide且persisted===true;还原需区分冷启动与热恢复,并清除旧快照。

页面进入 discarded 状态时,JavaScript 已被完全终止,**没有任何事件、回调或 API 能在丢弃发生时被触发**。你无法“实时判断原因”,只能在用户重新打开该 Tab 后,通过上下文线索**反向推测**它曾被丢弃,并大致归因于资源压力或系统策略。
为什么 discarded 无法被主动捕获
Discard 是浏览器彻底卸载页面的过程:JS 执行环境销毁、所有定时器清空、网络请求中断、监听器失效、beforeunload 和 pagehide 均不触发。这不是一个生命周期“事件”,而是一个不可逆的终态结果。
你唯一能做的,是在下次加载时观察启动方式和残留痕迹:
-
pageshow事件中event.persisted === false—— 表示本次是全新加载,不是从缓存恢复 - 检查 URL 是否含
?_reloaded=1等人工标记(需上一次页面冻结前主动写入) - 读取
localStorage中保存的时间戳,若距当前超过 5 分钟,大概率已被 discard(Frozen 通常只维持 2–3 分钟) - 调用
performance.getEntriesByType('navigation')[0]?.type,值为'reload'或'navigate'可能对应 discard 后重建
discard 的常见诱因(基于设备与场景)
Discard 不是随机发生的,而是系统级资源调度的结果。主要诱因有三类:
- 内存严重不足:低端 Android 设备后台开多个 Tab 或运行大型 App 时,浏览器会优先 discard 长时间冻结的页面
- 进程被系统强制终止:iOS 在后台长时间未响应、或电池优化开启时,可能直接 kill WebView 进程
- 用户主动清理:从任务管理器滑掉 Tab、使用“清除所有标签页”功能,也会导致 discard 行为(区别于普通关闭)
如何区分 discard 与普通 reload 或导航
关键看 document.wasDiscarded 和加载行为的组合:
-
document.wasDiscarded === true:仅在 discard 后首次 JS 执行时为真,刷新后即变 false —— 这是最直接的 discard 证据 -
pageshow触发 +event.persisted === false+document.wasDiscarded === true→ 高概率为 discard 恢复 - 若
document.wasDiscarded === false但event.persisted === false,更可能是用户手动刷新或新打开链接
真正可控的预防点:别等 discard,盯紧 freeze 和 pagehide
既然 discard 无法拦截,就应在它发生前完成状态保存。可靠时机只有两个:
- freeze 事件:页面即将冻结,JS 仍可执行,DOM 和内存尚存 —— 此时必须同步保存关键状态
-
pagehide 且
event.persisted === true:表示页面将被缓存(BFCache 或 Frozen),是 freeze 的补充兜底
在这两个时机里,记录时间戳、标记状态、序列化表单值/滚动位置/当前 tab 等轻量数据到 sessionStorage 或 localStorage,才能为 discard 后的冷启动恢复提供依据。

















