Leaflet js - 内存泄漏访问 GeoJSON REST Api

Leaflet js - memory leak accessing GeoJSON REST Api

使用Leaflet,我需要刷新地图移动(平移、缩放)后显示的功能。

我访问 GeoJSON REST Api 因此:

function getFeatures( map, layer, table, user ) {
  var bounds = map.getBounds();
  var style = layer.module.spatial.style || undefined;

  var params = {
    geojson: true,
    bbox: bounds.toBBoxString(),
    srs: 'EPSG:4326',
    limit: 200 // limit returned features
  }; 

  fetch ('api/organisations/' + user.organisation + '/objects/' + table + '?' 
    + new URLSearchParams (params))
  .then( response => response.json())
  .then( data => {
    layer.addData (data)
  })
  .catch( err => {
    console.log("Fetch error on table " + table + ': ' + err);
  });
}

export default function(options, map, L, user) {
  var layer = L.geoJson(null, { /*... styling, popup ...*/ });

  map.on('moveend', function(evt) {
    var map = evt.target;
    getFeatures(map, layer, options._id, user );
  });
}

/*
 * ... in calling script:
 */
map.addLayer(layer);

一切正常,但内存使用量(在 Chrome devtools 中测量)稳步上升,性能变差。

我想我需要释放一些东西,大概是在我的“moveend”处理程序中,但一直无法找到任何建议我应该做什么的例子。

我试过 map.removeLayer(layer)map.addLayer(layer) 两边 layer.addData (data),这没什么区别。

怎么办?

正在检查 leaflet.js 文档,图层似乎有一个 remove method。但是为了调用它,您可能需要获取对 geojson 图层对象的引用。所以也许像下面这样?

function getFeatures( map, layer, table, user ) {
  var bounds = map.getBounds();
  var style = layer.module.spatial.style || undefined;

  var params = {
    geojson: true,
    bbox: bounds.toBBoxString(),
    srs: 'EPSG:4326',
    limit: 200 // limit returned features
  }; 

  fetch ('api/organisations/' + user.organisation + '/objects/' + table + '?' 
    + new URLSearchParams (params))
  .then( response => response.json())
  .then( data => {
    layer.addData (data)
  })
  .catch( err => {
    console.log("Fetch error on table " + table + ': ' + err);
  });
}

let layer // not a huge fan of using var, but I believe you can use var here if you insist

export default function(options, map, L, user) {
  if (!!layer) {
    layer.remove()
  }
  layer = L.geoJson(null, { /*... styling, popup ...*/ });

  map.on('moveend', function(evt) {
    var map = evt.target;
    getFeatures(map, layer, options._id, user );
  });
}

/*
 * ... in calling script:
 */
map.addLayer(layer);

您可能需要做一些去抖动,因为 getFeatures 等是一个异步调用,您可能会遇到一些竞争条件恶作剧。

感谢@pandamakes 的回答,我的代码是这样结束的:

let layer;

function getFeatures( map, L, options, user ) { // Called on every map pan/zoom
  var table = options._id;
  if (!! layer) {
    layer.remove();
  }

  if(options.spatial.geometry == 'polygon') {
    layer = L.geoJson(null, {
      style: function (feature) {
        return feature.style || undefined;
      },
      onEachFeature: function (feature, layer) {
        layer.bindPopup(feature.properties.plats_namn); 
      }
    });
  } else {
    layer = L.geoJson(null, {
      pointToLayer: function (feature, latlng) {
        return L.circleMarker(latlng, feature.style || undefined);
      },
      onEachFeature: function (feature, layer) {
        layer.bindPopup(feature.properties.art);
      }
    });
  }

  /* 
   * Set the module on the source for filtering 
   */
  layer.module = options;
  layer.name = name;

    var bounds = map.getBounds();
    var style = layer.module.spatial.style || undefined;

    var params = {
      geojson: true,
      bbox: bounds.toBBoxString(),
      srs: 'EPSG:4326'
      style: style,
      limit: 200
    }; 

    fetch ('api/organisations/' + user.organisation + '/objects/' + table + '?' 
      + new URLSearchParams (params))
    .then( response => response.json())
    .then( data => {
      layer.addData (data)
      map.addLayer(layer)
    })
    .catch( err => {
console.log("Fetch error on table " + table + ': ' + err);
    });
}

export default function(options, map, L, user) {
  map.on('moveend', function(evt) {
    var map = evt.target;
    getFeatures(map, L, options, user );
  });
}

不满意,但内存泄漏消失了...

最好在每个 pan/zoom 上简单地删除图层上的现有功能;我将研究这样做的可能性。