selfm
selfm

Reputation: 101

Javascript memory leaks with JVectorMap

I must use javascript for a project but I don't know anything about javascript. In the js file I use jVectorMap to display a world map which is "updated" every 5 seconds. When I open the web page using this javascript file in my web client and wait for some hours my computer runs out of RAM. I use chrome dev console and profile tool to identify the part of the code producing this issue. When I remove this part there is no memory usage issue.

The part of the code is :

function ui_geo_map(countriesCount) {
    $('#geo-world-map').empty();
    $('#geo-world-map').vectorMap({
        map: 'world_mill_en',
        series: {
            regions: [{
                values: countriesCount,
                scale: ['#2ecc71', '#c0392b'],
                normalizeFunction: 'polynomial',
                legend: {vertical: true}
            }]
        },
        onRegionTipShow: function(e, el, code){
            el.html(el.html() + ' (' + countriesCount[code] + ' - servers)');
        }
    });
};

function ui_geo() {
    console.debug('Redrawing the geo map');
    $('.pywos-geo').remove();
    $.getJSON('/get/geo/all', function(data){
        $.each(data, function(key, val){
            countriesCount[val.country_code] = val.count;
        });
        ui_geo_map(countriesCount);
    });
};

I know the empty followed by vectorMap is certainly not the right way to do it but if I remove $('#geo-world-map').empty(); the map is not replaced, instead it is displayed under the previous one which is not what I want.

Can someone help me find the right way to do it without any memory leaks ?

Upvotes: 1

Views: 210

Answers (1)

bjornd
bjornd

Reputation: 22941

First of all there is a method remove which you should call on jVectorMap instance which gracefully removes all the DOM elements and linked JS objects:

var map = new jvm.Map({
    container: $('#geo-world-map'),
    map: 'world_mill_en',
    series: {
        regions: [{
            values: countriesCount,
            scale: ['#2ecc71', '#c0392b'],
            normalizeFunction: 'polynomial',
            legend: {vertical: true}
        }]
    },
    onRegionTipShow: function(e, el, code){
        el.html(el.html() + ' (' + countriesCount[code] + ' - servers)');
    }
});

Also there is not need to recreate the whole map every time you need to update values (this is a great waste of resources), you can just update data:

$.getJSON('/get/geo/all', function(data){
    $.each(data, function(key, val){
        countriesCount[val.country_code] = val.count;
    });
    map.series.regions[0].setValues(countriesCount);
});

Upvotes: 1

Related Questions