OpenLayers 3 TileCache导致浏览器使用CQL过滤器耗尽内存

时间:2016-12-09 21:38:22

标签: javascript caching openlayers-3

我目前正在运行OpenLayers 3.2.1。我有一个wms tile图层,在地图上显示各种多边形,wms图块层显示状态边界。目标是让用户能够点击状态,在getFeatureInfo请求中检索状态边界的坐标,然后使用坐标过滤第一层以仅显示该状态内的多边形。

每个多边形中有大量的点,具有CQL过滤器的图层的网址远远超过了网址长度限制。使用tileLoadFunction我将请求转换为POST以绕过它。取自这个答案:https://gis.stackexchange.com/questions/175057/openlayers-3-wms-styling-using-sld-body-and-post-request

一切正常,单击状态时正确过滤第一层。问题是在点击TileCache使用的内存量之后,因为存储在其中的URL太长了。第一次单击后,整个应用程序的速度变慢了。稍后点击几下,浏览器崩溃了。使用chrome,前后快照之间的比较显示,纯粹来自TileCache中这些URL的存储增加了179MB。

我试图阻止缓存,但OpenLayers要求缓存加载图层。我已经尝试在加载图层后清除缓存但在我的版本中似乎没有明确的方法来知道图层加载完成的确切时刻。我尝试在长时间超时后清除缓存,但由于某种原因缓存在之后不断填满。最后我尝试设置一个间隔来定期清除缓存,但缓存只是继续填充到原始点。

以下是缩小的代码:

var params = getWMSParams(jsonLayerConfig, map);
var options = {
    url: geoserverUrl,
    params: params,
    tileLoadFunction: function(image, src) {
        convertToPost(image, src);
    }
};

var source = new ol.source.TileWMS(options);

var polygonLayer = new ol.layer.Tile({
    source : source
});

// states layer is created the same way then both are added to map.

var getCqlGeometry = function(coords) {
    var geomString = '';
    if (typeof(coords[0]) === 'number') {
        geomString = coords[0] + ' ' + coords[1];
    } else {
        var geomString = '(';
        var subGeoms = [];
        for (var i = 0, len = coords.length; i < len; i+=1) {
            var coord = coords[i];
            subGeoms.push(getCqlGeometry(coord));
        }
        geomString += subGeoms.join(',') + ')';
    }
    return geomString;
}

var setCqlFilter = function(featureInfo) {
    var geomString = getCqlGeometry(featureInfo.coords);
    var cqlFilter = "WITHIN(geom,MULTIPOLYGON"+geomString+")";

    // Some code here updates the layers in the map.
}

map.on('click', function(event) {
    var featureInfo = getFeatureInfo(event.coordinate);
    setCqlFilter(featureInfo);
});

var convertToPost = function(image, src) {
    var img = image.getImage();
    if (typeof window.btoa === 'function') {
        var xhr = new XMLHttpRequest();
        var url = src.substr(0, src.indexOf('?'));
        var params = src.substring(src.indexOf('?')+1);
        xhr.open('POST', url, true);

        xhr.responseType = 'arraybuffer';
        xhr.onload = function(e) {
            if (this.status === 200) {
                var uInt8Array = new Uint8Array(this.response);
                var i = uInt8Array.length;
                var binaryString = new Array(i);
                while (i--) {
                    binaryString[i] = String.fromCharCode(uInt8Array[i]);
                }
                var data = binaryString.join('');
                var type = xhr.getResponseHeader('content-type');
                if (type.indexOf('image') === 0) {
                    img.src = 'data:' + type + ';base64,' + window.btoa(data);
                }
                uInt8Array = null;
            }
        };
        //SET THE PROPER HEADERS AND FINALLY SEND THE PARAMETERS 
        xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        xhr.send(params);
    } else {
        img.src = src;
    }
}

我有可能更新到最新的OpenLayers 3版本(撰写本文时为3.19.1),但我需要足够的理由给我的雇主。

修改

我能够根据ahocevar的评论让它工作。由于json层配置中的每一层都分配了一个自动生成的id,我将这个id添加到了图层params,在tileLoadFunction中解析了该参数的url,然后检索了该层的json配置(json配置也保存了cql)过滤)。我仍然希望有一种方法来阻止缓存,但现在这个解决方案可行。谢谢ahocevar。

0 个答案:

没有答案