default··约 13 分钟读完

useCesiumCache Cesium 资源缓存工具使用文档

useCesiumCache 是一个 Cesium.js 资源缓存工具,通过拦截底层请求将符合条件的资源自动缓存到 IndexedDB。主要特性包括:无缝集成、持久化存储、可配置缓存策略(URL/自定义键)、智能拦截指定响应类型(默认 blob/arraybuffer)、缓存管理和调试模式。使用时需提前初始化,支持自定义缓存键和排除特定请求。注意事项包括单例行为、版本兼容性、缓存更新策略等。该工具可显著提升 3D 场景加载速度,减少网络请求,并提供基础离线能力。
前端javascript缓存

useCesiumCache Cesium 资源缓存工具使用文档

概述

useCesiumCache 是一个针对 Cesium.js 的请求缓存工具,通过拦截 Cesium 底层资源加载方法(Cesium.Resource._Implementations.loadWithXhr),将符合条件的请求响应(如 blobarraybuffer)自动缓存到浏览器的 IndexedDB 中。当同一资源再次被请求时,直接从本地缓存返回,大幅减少网络请求、提升 3D 场景的加载速度,并支持一定的离线能力。

功能特性

  • 🚀 无缝集成:只需调用一次初始化函数,即可自动拦截所有 Cesium 的 Resource 请求,无需修改现有 Cesium 业务代码。
  • 💾 IndexedDB 持久化:利用浏览器 IndexedDB 存储二进制数据(Blob/ArrayBuffer),容量大、持久化保存,页面刷新后依然有效。
  • 🎯 可配置缓存策略
    • 支持按 URL 或自定义键(key 函数)缓存。
    • 可指定缓存的响应类型(如 "blob""arraybuffer")。
    • 可选择性忽略某些请求(通过返回空字符串的 key 函数)。
  • 🧠 智能拦截:仅对匹配 typesresponseType 进行缓存操作,其他请求(如 jsontext)按原始流程处理。
  • 📊 缓存管理:提供清除所有缓存、获取缓存大小的方法,便于维护。
  • 🔍 调试模式:开启 debug: true 后控制台会输出缓存命中/未命中/存储的日志,方便开发和调优。

依赖要求

  • Cesium.js:项目需已引入 Cesium(版本不限,但建议使用较新版本),并可通过全局 Cesium 对象访问,或通过 import * as Cesium from 'cesium' 引入。
  • useLocalStore:工具内部依赖 sunrise-utils 中的 useLocalStore 模块,该模块封装了 IndexedDB 的基础操作(getCacheByKeysetCacheToLocalclearCachegetCacheSize)。如果你的项目中没有该模块,请确保有对应的实现或从合适路径导入。

配置参数

调用 useCesiumCache(config, Resource?) 时可传入以下配置对象:

参数类型默认值描述
dbNamestring"LocalStore"IndexedDB 数据库名称,将透传给 useLocalStore
key(url, responseType, method, data, headers) => string(url) => url生成缓存键的函数,返回的字符串将作为存储的 key。若返回空字符串(""),则不缓存该请求。可用于实现精细化缓存策略(如忽略某些 URL 或带参数的请求)
typesArray<ResponseType>["blob", "arraybuffer"]需要缓存的响应类型数组。只有请求的 responseType 在此列表中时,才会尝试缓存。Cesium 中常见的类型有 "blob"(影像瓦片、地形等)和 "arraybuffer"(3D Tiles、模型等)
debugbooleanfalse是否在控制台输出缓存操作日志(命中、未命中、已存储)

参数详解

  • key 函数:接收请求参数,返回唯一标识该资源的键。默认使用 url 作为键。如果你的瓦片 URL 包含时间戳或会话参数导致同一资源 URL 变化,可通过自定义 key 函数去除无关参数,实现共享缓存。例如:key: (url) => url.split('?')[0] // 忽略查询参数
    若返回 "",则请求不会被缓存,直接走网络。
  • types 数组:Cesium 内部 loadWithXhr 可能请求多种类型数据,如 "json"(样式文件)、"text"(某些元数据)。通常我们只需缓存体积较大的二进制数据,因此默认只缓存 "blob""arraybuffer"。可根据需要添加其他类型,但不建议缓存文本类型,以免干扰实时更新。

返回对象方法

调用 useCesiumCache 后返回一个对象,包含以下方法:

clear(): void

清除所有缓存的资源(即清空整个 IndexedDB 数据库)。调用后所有已缓存的瓦片、模型等将被删除,下次请求会重新从网络加载。

getCacheSize(): Promise<string>

获取当前缓存的总大小,返回一个格式化的字符串(如 "1.2 MB")。此方法直接透传 useLocalStore.getCacheSize() 的结果。

注意:返回的对象中还可能包含其他内部属性,但主要使用上述两个方法。useCesiumCache 设计为单例模式,多次调用不会重复拦截,且每次返回相同的缓存管理对象。

使用示例

1. 基础用法(自动拦截所有 Cesium 请求)

import * as Cesium from 'cesium'; import { useCesiumCache } from './useCesiumCache'; // 初始化缓存(只需在应用启动时调用一次) useCesiumCache({ debug: true, // 开发环境下可开启调试 }); // 之后正常使用 Cesium,所有影像、地形、3D Tiles 等请求都会被自动缓存 const viewer = new Cesium.Viewer('cesiumContainer');

2. 自定义缓存键(忽略 URL 中的版本参数)

useCesiumCache({ key: (url, responseType, method, data, headers) => { // 例如 https://example.com/tiles/{z}/{x}/{y}?v=123 => https://example.com/tiles/{z}/{x}/{y} return url.split('?')[0]; }, debug: true, });

3. 排除某些 URL 不缓存

useCesiumCache({ key: (url) => { if (url.includes('/dynamic/')) { return ''; // 返回空字符串表示不缓存动态数据 } return url; }, });

4. 管理缓存(清除/查看大小)

const cache = useCesiumCache({ debug: false }); // 获取缓存大小并显示 cache.getCacheSize().then(size => { console.log(`当前缓存占用: ${size}`); }); // 用户点击“清除缓存”按钮时 document.getElementById('clear-cache').onclick = () => { cache.clear(); alert('缓存已清除'); };

5. 与现有 Cesium 代码集成(确保拦截生效)

拦截器在第一次调用 useCesiumCache 时被安装。务必在所有 Cesium 资源请求发生之前调用它。通常放在应用入口文件(如 main.tsindex.ts)中,并在创建 Cesium.Viewer 之前执行。

工作原理(简要)

  1. 工具通过替换 Cesium.Resource._Implementations.loadWithXhr 方法实现对 Cesium 底层网络请求的拦截。
  2. 对于每个请求,根据 config.key 生成缓存键,并判断 responseType 是否在 config.types 中。
  3. 若需缓存,先查询 IndexedDB 是否已有对应键的数据。
    • 命中:直接使用缓存数据,通过 deferred.resolve 返回,避免网络请求。
    • 未命中:调用原始 loadWithXhr 发起网络请求,并在请求成功后通过包装的 resolve 将数据存入 IndexedDB。
  4. 使用 used 标志确保拦截逻辑只安装一次,避免重复覆盖。

注意事项

  • 单例行为:多次调用 useCesiumCache 只有第一次会安装拦截器,后续调用均返回相同的缓存管理对象。因此你可以在多个模块中调用它,但最好只在入口调用一次。
  • Cesium 版本兼容性:工具依赖于 Cesium 内部 Resource._Implementations.loadWithXhr 的接口。不同 Cesium 版本该结构可能发生变化。目前测试于 Cesium 1.80+,若遇到拦截失效,请检查对应版本的 Cesium 源码,调整代码中的类型定义或属性访问路径。
  • 跨域与 CORS:缓存的数据来源于网络请求,因此跨域资源仍需服务端支持 CORS,否则原始请求会失败,缓存也无法生效。
  • 缓存更新:默认策略是“一次缓存,永久使用”。若资源在服务端更新(如新版本地形数据),需要手动调用 clear() 清除缓存,或通过 key 函数加入版本标识(例如将版本号拼入 key)。
  • 异步初始化:IndexedDB 操作是异步的,但缓存查询在网络请求发起前完成,因此不会阻塞原始请求流程。若缓存查询失败(如 IndexedDB 异常),会自动回退到网络请求。
  • useLocalStore 的导入路径:示例中从 "sunrise-utils" 导入,请根据你的项目实际情况调整路径。若没有该模块,需要自行实现或替换为其他存储方案(如 idb 库),并确保导出方法签名匹配。

常见问题

Q:为什么我的缓存没有生效?
A:请检查:

  • 是否在所有 Cesium 请求之前调用了 useCesiumCache
  • 是否开启了 debug: true?控制台应输出 [CesiumCache] Miss:[CesiumCache] Hit: 日志。若没有任何日志,可能拦截器未正确安装。
  • 请求的 responseType 是否在 config.types 中?Cesium 默认缓存类型为 blobarraybuffer,如果你的请求是 jsontext,默认不会被缓存。
  • 自定义 key 函数是否返回了空字符串导致被忽略?

Q:清除缓存后,下次请求会重新下载吗?
A:是的,调用 clear() 会删除所有 IndexedDB 中的缓存数据,之后所有请求都会重新从网络获取并再次缓存。

Q:缓存占用的空间有限制吗?
A:IndexedDB 没有严格的上限,但浏览器通常会根据可用磁盘空间动态分配。长时间使用可能导致缓存过大,建议提供管理界面让用户手动清除,或实现 LRU 淘汰策略(本工具暂未内置)。

Q:离线模式下能使用缓存的瓦片吗?
A:可以,只要之前访问过的区域已被缓存,即使断网也能正常显示。但首次访问的瓦片会因网络失败而无法加载。

Q:如何预缓存某些区域的瓦片?
A:可以手动遍历需要的瓦片坐标,构造 Cesium.Resource 对象发起请求,利用缓存拦截自动存储。例如使用 Cesium.Resource.fetchImageCesium.Resource.fetchArrayBuffer 来加载影像或地形。


通过 useCesiumCache,你可以轻松为 Cesium 应用添加强大的缓存能力,显著提升用户体验,尤其在重复浏览同一区域或需要离线使用的场景下。如有任何问题,欢迎反馈!