ajax-hook+indexDB+Cesium优化三维资源加载

2023-05-29  本文已影响0人  YGIS
无缓存下首屏加载120s
indexDB客户端存储数据后模型一步到位

参考资料

Ajax-hook原理解析
localforage中文文档

问题背景

一年前首次通过修改Cesium源码中Resource相关代码,实现了localforage缓存3dtiles瓦片,优化了体积较大的三维瓦片资源加载效率。


实现逻辑

最近由于升级Cesium以便支持I3S模型加载,需要重新在不修改Cesium源码的前提下重新实现上述优化。

实现思路

  1. 尝试从Cesium3DTileset中查找资源请求相关事件,确认cesium采用XHR请求资源。
  2. 查找一些重写XHR的方法,发现一般都对其他资源正常加载有影响。
  3. 找到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);
        },
      });
上一篇下一篇

猜你喜欢

热点阅读