深色模式
资源生命周期:离开页面之后
一个实验第一次打开正常,来回进入十次就变慢,常常不是算法越来越复杂,而是资源没有退出。JavaScript 对象不再使用,不代表关联 GPU 资源、Worker、事件监听与 object URL 已经释放。图层必须有与创建同样清楚的结束过程。
谁创建,谁负责结束
宿主通常拥有 Viewer;图层拥有它创建的纹理、缓冲、shader 引用、Worker 与监听器;输入 TypedArray 可以约定只读借用。资源所有权(resource ownership)应写在接口中,不能靠调用者猜测。借用的外部纹理不得随手销毁,自己创建的资源也不能期待其他图层负责清理。
Cesium 的 PrimitiveCollection 默认在移除图元时销毁它,行为由 destroyPrimitives 控制。若默认 remove 已执行销毁,再手动调用一次可能出错。反过来,如果明确关闭自动销毁,就需要保存引用并自行结束。组件卸载时销毁 Viewer,也不能代替对外部 Worker、浏览器事件和 fetch 的独立管理。
异步结果需要版本与存活检查
用户可能在请求尚未完成时切换数据或离开页面。AbortController 能取消部分请求,但不能撤回已经到达的 Worker 消息。每次更新增加 revision,让异步结果携带对应编号。下面是说明并发保护的伪代码:prepare() 代表应用自己的异步数据准备,apply() 代表将结果接入场景;二者不是 Cesium API。片段省略了请求取消、错误处理、disposed 的销毁赋值和结果资源释放,不能独立运行:
ts
let revision = 0;
let disposed = false;
async function update() {
const mine = ++revision;
const result = await prepare();
if (disposed || mine !== revision) return;
apply(result);
}实际程序还要释放被丢弃结果所拥有的资源。revision 检查避免“旧温度覆盖新温度”,存活检查避免“离开页面后重新创建图层”。销毁操作最好幂等(idempotent,即重复执行不再产生额外状态改变),重复调用能安全返回。
隐藏、暂停与销毁不同
隐藏图层可能只是不提交绘制,GPU 内存仍存在;暂停粒子可能停止计算,仍保留状态;销毁才结束资源。根据用户返回频率选择保留或释放,但不要把 show=false 当成内存已归零。
对于 Blob 底图,创建 object URL 的一方应在不再使用时 revoke;事件回调需要保留移除句柄;动画循环需要 cancel 或停止提交。一次成功 destroy 不足以证明无泄漏,应反复进入、退出和快速切换数据。
资源的一生
添加、隐藏、移除对象,理解所有权与销毁。
在浏览器本地运行 · 无需账号 · 鼠标拖动旋转,滚轮缩放
底图:Natural Earth II(公共领域);其余几何和地形为教学合成。 数据说明
查看运行源码
此代码直接读取实际运行的实验模块。按 kind 分支定位当前实验,也可查看数据公式和 GLSL。
读取源码…观察任务
反复创建与销毁实验中的场景,观察状态变化。若关闭面板后仍有网络请求或粒子更新,应该检查哪里?把全部变量设为 null,是否已经完成清理?
展开答案
检查 Worker、事件、定时器、未取消请求和迟到的异步结果。null 只移除某个引用,不会自动执行 WebGL 与外部系统的清理协议。应通过各资源的释放方法结束它们,再清空应用引用;也要避免误销毁借用资源。
阅读依据:Cesium 1.145 PrimitiveCollection、Cesium 1.145 destroyObject。