当前位置: 首页 > news >正文

浏览器端缓存地图请求:使用 IndexedDB + ajax-hook 提升地图加载速度

前言

        在 Web 地图应用中(例如基于 CesiumJS、mars‑3d 或其它 3D 地球/地图库),一个常见性能瓶颈是“底图/地形/瓦片/影像请求过多、网络延迟高、重复请求资源多”。

        为了解决这个问题,可以将重要的地图请求结果缓存到浏览器端(使用 IndexedDB),下一次再请求相同 URL 时,优先从缓存返回,从而减少网络请求、加快加载速度、改善用户体验。本文将演示如何使用 localforage(用于 IndexedDB 存储) + ajax‑hook(用于拦截 XHR/Fetch 请求)实现这一功能。


核心思路

  • 拦截所有发出的 AJAX 请求(通过 ajax-hook)

  • 对符合特定规则(例如天地图、ArcGIS 地形服务等)的请求,先检查浏览器缓存(IndexedDB)是否已有响应数据

  • 如果缓存命中,则直接返回缓存数据,避免真实网络请求

  • 如果缓存未命中,则让请求继续,响应回来后,再将结果写入缓存,以便下次使用

这样做的好处包括:

  • 减少重复请求,减轻服务器和网络负担

  • 缩短客户端加载时间,提升性能

  • 优化弱网络或移动设备上的用户体验

        在地图应用中,这种缓存尤其有意义,因为很多瓦片/地形/影像都是“可复用”的、被多次请求的资源。早在 Cesium 社区就有人讨论过将瓦片存入 IndexedDB 用作离线或加速方案。 Cesium Community+1


代码详解及意义

下面是完整代码(你已提供)并附上详细说明:

import localforage from 'localforage';
import { proxy } from 'ajax-hook';const cache = localforage.createInstance({name: 'mapRequestCache',driver: localforage.INDEXEDDB,
});const rules = [/tianditu\.gov\.cn\/DataServer/,/elevation3d\.arcgis\.com\/arcgis\/rest\/services\/WorldElevation3D\/Terrain3D\/ImageServer/
];function isMatchRule(url) {return rules.some((rule) => rule.test(url));
}function getKey(url, method, version = 'v1') {return `${version}-${url}-${method}`;
}proxy({onRequest: async (config, handler) => {const url = config.url;if (isMatchRule(url)) {const key = getKey(url, config.method);const data = await cache.getItem(key);if (data) {handler.resolve({config,status: 200,response: data,header: config.headers});return;}}return handler.next(config);},onResponse: async (response, handler) => {const url = response.config.url;if (response.status === 200 && isMatchRule(url)) {const key = getKey(response.config.url, response.config.method);await cache.setItem(key, response.response);}return handler.next(response);}
});export default cache;

下面按模块逐一解释其意义与作用:

1. 引入 localforage 与 ajax-hook

import localforage from 'localforage';
import { proxy } from 'ajax-hook';
  • localforage:一个包装 IndexedDB、Web SQL 和 localStorage 的库,提供统一异步 API,用于在浏览器中存储较大数据(例如图片、瓦片、二进制 Blob)。

  • ajax-hook:一个用来拦截 XHR/Fetch 请求的库。它允许你在请求发出前(onRequest)和响应返回后(onResponse)插入逻辑,从而可实现缓存、修改请求/响应、阻止请求等。 GitHub

2. 创建缓存实例

const cache = localforage.createInstance({name: 'mapRequestCache',driver: localforage.INDEXEDDB,
});
  • 这里创建了一个 localforage 实例,命名为 'mapRequestCache',并明确指定 driver: localforage.INDEXEDDB,即使用浏览器的 IndexedDB 存储。

  • 这意味着你的缓存数据将以键值对形式保存在 IndexedDB 中(比 localStorage 容量更大、性能更好)。

3. 定义要拦截/缓存的 URL 规则

const rules = [/tianditu\.gov\.cn\/DataServer/,/elevation3d\.arcgis\.com\/arcgis\/rest\/services\/WorldElevation3D\/Terrain3D\/ImageServer/
];function isMatchRule(url) {return rules.some((rule) => rule.test(url));
}
  • rules 数组中定义了若干正则表达式,匹配你希望缓存的地图服务请求 URL(如 天地图 “tianditu.gov.cn/DataServer”、ArcGIS 地形服务 “elevation3d.arcgis.com/…Terrain3D/ImageServer”)。

  • isMatchRule(url) 函数用于判断一个 URL 是否匹配这些规则。如果匹配,则说明这是一个“值得缓存”的请求。

  • 你可以根据自己的项目,扩展或修改这些规则(例如增加瓦片服务、3DTiles、贴图 URL 等)。

4. 生成缓存 Key

function getKey(url, method, version = 'v1') {return `${version}-${url}-${method}`;
}
  • 每个缓存条目需要一个唯一 key,以便存取。这里用 ${version}-${url}-${method} 来生成。

  • url:请求的 URL

  • method:请求方法(如 GET、POST)

  • version:可选版本号,用于在服务更新/格式变更时“失效”旧缓存。

  • 使用版本号是一个好习惯:当底图服务、瓦片格式、API 版本发生变动时,通过改变 version 值即可让 key 全部不同,从而避免使用过期缓存。

5. 拦截请求(onRequest)

onRequest: async (config, handler) => {const url = config.url;if (isMatchRule(url)) {const key = getKey(url, config.method);const data = await cache.getItem(key);if (data) {handler.resolve({config,status: 200,response: data,header: config.headers});return;}}return handler.next(config);
}

意义说明:

  • 在请求发送之前,这里检查 config.url 是否匹配规则(即 isMatchRule(url))。

  • 如果匹配,则尝试从 cache.getItem(key) 获取缓存数据。

  • 如果缓存命中(即 data 不为空),就 直接返回缓存结果,通过 handler.resolve() 模拟一个成功响应,从而跳过真实网络请求

  • 如果缓存未命中,则调用 handler.next(config),让请求继续发送。

这样就实现了“优先使用缓存”的逻辑。

6. 拦截响应(onResponse)

onResponse: async (response, handler) => {const url = response.config.url;if (response.status === 200 && isMatchRule(url)) {const key = getKey(response.config.url, response.config.method);await cache.setItem(key, response.response);}return handler.next(response);
}

意义说明:

  • 真实网络请求返回后,首先检查 response.status === 200url 匹配规则。

  • 如果满足,则生成缓存 key ,并将 response.response 存入缓存。

  • 然后调用 handler.next(response) 继续处理响应(例如传递给业务逻辑)。

这样就保证了“第一次请求网络 → 写入缓存;以后相同请求 → 直接读缓存”的流程。

7. 导出缓存实例

export default cache;
  • 导出 cache 实例,方便在其它模块中对缓存进行管理/清理/查询。

  • 比如你可能想在特定场景下清理缓存、查看缓存条目数、打印日志等。


使用步骤与实践建议

下面是你在地图项目中(例如使用 mars-3d/Cesium)建议的使用流程与注意事项:

  1. 在项目入口处初始化
    在项目的最早期(如 main.js、入口 script 中)引入上述缓存模块,使其在页面加载初期即激活拦截器。

    import './mapRequestCache.js';
    
  2. 定义合适的规则(rules)
    根据你的项目中所用的地图服务类型(瓦片、地形、影像、3DTiles、模型等)调整 rules 正则。例如:

    /.*tianditu\.com\/DataServer.*/,
    /.*tileserver\.yourdomain\.com\/tiles\/.*/,
    /.*3dtiles\.yourservice\.com\/tileset.json/,
    /.*\.glb$/,
    

    这样保证你缓存了对性能影响最大的资源。

  3. 考虑资源格式与缓存大小

    • 场景中可能请求的是 图片瓦片 (PNG/JPG)、**二进制 ArrayBuffer/Blob **、JSON/3DTiles json。你需要确认 ajax-hook 拦截时 response.response 是否包含你想缓存的数据(可能是字符串、二进制)。

    • 如果资源体量很大(例如高分辨率瓦片、影像、大 3DTiles 包),缓存可能占用大量 IndexedDB 空间。你要考虑:缓存条目数控制缓存大小控制版本切换机制

    • 在某些场景,浏览器自身的 HTTP 缓存/服务工作者缓存也可能起作用。你要测试确保你的机制是真实起效。

  4. 测试缓存命中 + 加载速度提升

    • 使用浏览器 DevTools → Network 面板,观察某个瓦片或地形请求第一次时有网络请求,第二次是否被缓存拦截(无网络请求或网络请求被替换为本地返回)。

    • 检测对 mars-3d 场景加载速度是否有显著提升。

    • 测试弱网络或手机设备情况,缓存机制通常对它们提升更明显。

  5. 处理版本或服务变动

    • 当地图服务底图/瓦片格式/参数发生变更时,你要“让缓存失效”,避免服务更新但客户端使用了旧缓存。可通过改变 version 参数(如 'v2')或清理旧 key 实现。

    • 你还可以在缓存模块里加入清理逻辑:例如每次版本变动就 cache.clear()

  6. 监控 IndexedDB 使用情况

    • 定期查看浏览器 Application 面板 → IndexedDB → mapRequestCache 库,观察条目数、存储大小。

    • 如果缓存数据过多,可以实现“最少使用淘汰(LRU)”逻辑、或定期清理旧条目。


注意事项与风险提示

  • 并非所有请求都能被 ajax-hook 成功拦截。例如使用 img 标签、Canvas、WebGL 纹理加载、或者某些 fetch / Resource.fetch 机制可能绕过你的代理。你需要验证在你的地图库(例如 mars-3d)中实际资源加载方式。

  • 如果地图服务严格依赖 CORS 、或返回 ArrayBuffer/Blob 数据,缓存读取与返回时可能需要做额外处理(如 Blob 转 ObjectURL、Base64 编码等)。

  • 缓存如果使用不当可能导致“旧数据展示”或“风格/内容与服务器不一致”的问题。必须做好版本控制。

  • 浏览器不同平台对于 IndexedDB 大小、性能支持不同。在容量较低或私有模式下可能受限。

  • 使用第三方地图服务(如 天地图、ArcGIS Online)时,需确认其服务协议允许客户端缓存;部分服务可能限制缓存或离线使用。


总结

        通过这段代码,你可以在浏览器中为地图应用构建一个“请求拦截 + 本地缓存”机制,从而显著提升地图加载性能、减少重复网络请求。关键在于:

  • 明确哪些资源值得缓存(瓦片、地形、影像、3D 模型等)

  • 拦截请求 + 返回缓存 +写入缓存的流程

  • 版本控制与缓存管理。

        如果你在项目中使用 mars‑3d,建议将这段缓存逻辑与底图/地形图层的加载流程结合起来使用,并在实际设备(尤其是移动设备/弱网络)上做性能测试。

http://www.dtcms.com/a/565317.html

相关文章:

  • 地铁工程建设论文投稿网站谷歌广告代运营
  • 广东备案网站软件开发怎么学
  • 【成长纪实】鸿蒙 ArkTS 语言从零到一完整指南
  • PyTorch模型部署实战:从TorchScript到LibTorch的完整路径
  • 网站开发后台结构江西建设职业技术学院网站
  • 如何导出VSCode的已安装扩展列表?
  • 高级系统架构师笔记——系统质量属性与架构评估(1)软件系统质量属性
  • Vscode参数设置及使用记录ubuntu2204(更新中)
  • Linux上vscode c/c++开发环境搭建详细-abuild
  • vscode多文件编程bug记录
  • 分布式答案解析
  • 做耳机套的网站常用网站推广方法的适用性
  • 网站建设增长率呼和浩特建设厅网站
  • AI 音乐工具 Suno 和 Producer 对比
  • KeilIDE背后的命令
  • flash中文网站模板带有flash的网站
  • 阿里云核心服务解析与应用实践
  • Android BaseDexClassLoader源码阅读
  • 笔记本蓝牙怎么开启 完整教程
  • 【Delphi】获取电脑唯一码(一机一码)
  • 钉钉的设计理念方面,我可以学习
  • qq恢复官方网站浅谈海尔的电子商务网站建设
  • 怎么看电脑显卡什么型号?显卡配置方法查看指南
  • 【C#】WinForms 控件句柄与 UI 刷新时机
  • Go语言设计模式:迭代器模式详解
  • 中科大少年班记(2025年11月)
  • 顺德网站建设咨询大连鼎信网站建设公司地址
  • Android15跟踪函数调用关系
  • 公司网络推广网站就选火13星仁德短网址生成算法
  • 如何使网站能被百度搜到福建省第一电力建设公司网站