indexDB客户端存储数据后模型一步到位
参考资料
问题背景
一年前首次通过修改Cesium源码中Resource相关代码,实现了localforage缓存3dtiles瓦片,优化了体积较大的三维瓦片资源加载效率。
实现逻辑
最近由于升级Cesium以便支持I3S模型加载,需要重新在不修改Cesium源码的前提下重新实现上述优化。
实现思路
- 尝试从
Cesium3DTileset
中查找资源请求相关事件,确认cesium
采用XHR
请求资源。 - 查找一些重写
XHR
的方法,发现一般都对其他资源正常加载有影响。 - 找到
ajax-hook
库,实现了上图功能逻辑。ajax-hook
库提供了一种方式来拦截和重写XHR
请求,从而实现对请求的控制和修改。使用ajax-hook
,我们可以在请求发送之前或响应返回之后对XHR对象进行处理。这使得我们可以在Cesium
中使用ajax-hook
库来拦截和修改3D Tiles
资源请求,以满足我们的定制需求。
需要注意的是,在使用ajax-hook
库进行XHR
重写时,我们应该谨慎处理,以避免对整个应用程序的网络请求产生意外的影响。确保我们只拦截和修改与3D Tiles
资源加载相关的请求,并在处理完请求后恢复正常的XHR
行为。这样可以确保我们的功能逻辑与其他资源加载不会发生冲突,并保持应用程序的稳定性和性能。
代码
// 初始化localstorage
const store = localforage.createInstance({
name: "MyDB",
});
const storeUrls = [];
storeUrls.push(
"../gisserver/3DTiles/3DModel/tileset.json?t=1"
);
// proxy请求拦截
unProxy();
proxy({
onRequest: async (config, handler) => {
const { url } = config;
const needDB = storeUrls.reduce((pre, curr) => {
const path = curr.substring(0, curr.lastIndexOf("/") + 1);
return pre || url.includes(path);
}, false);
if (needDB) {
if (window.localStorage.getItem(url) === "1") {
const data = await store.getItem(url);
if (data) {
handler.resolve({
config,
status: 200,
// headers,
response: data,
});
return;
}
}
}
handler.next(config);
},
onResponse: (response, handler) => {
const {
config: { url },
} = response;
const needDB = storeUrls.reduce((pre, curr) => {
const path = curr.substring(0, curr.lastIndexOf("/") + 1);
return pre || url.includes(path);
}, false);
if (needDB) {
store
.setItem(url, response.response)
.then(window.localStorage.setItem(url, "1")); // Set a flag in local storage to indicate that the data is stored
}
handler.next(response);
},
});
网友评论