如何拦截esri-leaflet xhr请求然后检查CacheStorage API,如果缓存存在则返回缓存的要素层数据而不是发送真实的xhr

问题描述 投票:0回答:1

我的Web应用程序使用esri-leaflet包,它通过xhr加载geojson而不是从ArcGIS服务器获取。我试图使用以下代码来拦截xhr请求,但是,它不起作用,并且浏览器不渲染缓存数据,我不确定发生了什么......

代码运行良好,将数据保存到浏览器的缓存存储,然后成功检索数据,但无论我如何配置xhr响应,浏览器似乎都不会处理假xhr调用成功,并且不会反馈缓存数据.

const cache = await caches.open('my-cache');

(function() {
  var origOpen = XMLHttpRequest.prototype.open;
  var origSend = XMLHttpRequest.prototype.send;
  var targeturl, rs;
    
  XMLHttpRequest.prototype.send = async function() {
    var self = this;
    // Check for cached response before sending the request
    const cachedResponse = await caches.match(targeturl, {
      //ignoreSearch: true, //true will ignore querystring
      ignoreMethod: true,
      ignoreVary: true
    });

    if (cachedResponse) {
      // Use cached response
      rs = await cachedResponse.json();
      Object.defineProperty(self, 'status', {
            writable: true,
            configurable: true
        });
      Object.defineProperty(self, 'readyState', {
            writable: true,
            configurable: true
        });
      Object.defineProperty(self, 'responseText', {
            writable: true,
            configurable: true
        });
      Object.defineProperty(self, 'responseURL', {
            writable: true,
            configurable: true
        });
      Object.defineProperty(self, 'response', {
            writable: true,
            configurable: true
        });
      self.status = 200; // Set appropriate status code
      self.readyState = 4;
      self.responseText = JSON.stringify(rs); // Access cached response text
      self.response = JSON.stringify(rs);
      self.responseURL = targeturl;   
      self.dispatchEvent(new Event('loadstart'));
      self.dispatchEvent(new Event('load'));
      self.dispatchEvent(new Event('loadend'));
      
    } else {
      // Send the actual XHR request
      origSend.apply(self, arguments);
    }
  };

  XMLHttpRequest.prototype.open = function(method, url) {
    targeturl = url;  
    var self = this;

    // Corrected event listener logic
    self.addEventListener('loadstart', async (e) => {
      console.log('request started!');
      //try set response again as not working
      e.target.status = 200; // Set appropriate status code
      e.target.readyState = 4;
      e.target.responseText = JSON.stringify(rs); // Access cached response text
      console.log(e)
    });

    self.addEventListener('load', async (e) => {
      console.log('request completed!', e, rs);

      // Add response to cache if not already cached
      const cacheKeys = await cache.keys();
      const hit = cacheKeys.find((key) => key.url === url);
      if (!hit) {
        await cache.add(url); // Cache the actual response
      }
    });

    origOpen.apply(self, arguments);
  };
})();
browser leaflet xmlhttprequest esri-leaflet cacheapi
1个回答
0
投票

查看esri-leaflet源代码后,我弄清楚了readystatechange事件触发的featureLayer渲染逻辑。

以上代码全部正确,只需添加

self.dispatchEvent(new Event('readystatechange'));
© www.soinside.com 2019 - 2024. All rights reserved.