【问题标题】:Jquery/Javascript memory leakJquery/Javascript 内存泄漏
【发布时间】:2016-08-29 08:18:36
【问题描述】:

我有一个 Web 应用程序,它每 10 秒显示图表和更新图表状态。

HTML 是:

<div id="hoze-bar-chart"></div>

绘制图表的JS:

var handleStackedChart = function() {
  "use strict";

  function v(e, t, n) {
    $('<div id="tooltip" class="flot-tooltip">' + n + "</div>").css({
      top: t,
      left: e + 35
    }).appendTo("body").fadeIn(200);
  }
  var e = displaycount.e;
  var n = displaycount.n;
  var h = displaycount.h;

  var p = {
    xaxis: {
      tickColor: "transparent",
      ticks: h
    },
    yaxis: {
      tickColor: "#ddd",
      ticksLength: 10
    },
    grid: {
      hoverable: !0,
      tickColor: "#ccc",
      borderWidth: 0,
      borderColor: "rgba(0,0,0,0.2)"
    },
    series: {
      stack: null,
      lines: {
        show: !1,
        fill: !1,
        steps: !1
      },
      bars: {
        show: !0,
        barWidth: .5,
        align: "center",
        fillColor: null
      },
      highlightColor: "rgba(0,0,0,0.8)"
    },
    legend: {
      show: !0,
      labelBoxBorderColor: "#ccc",
      position: "ne",
      noColumns: 1
    }
  };
  var d = [{
    data: e,
    color: green,
    label: displaycount.totalTitle,
    bars: {
      fillColor: green
    }
  }, {
    data: n,
    color: red,
    label: displaycount.offlineTitle,
    bars: {
      fillColor: red
    }
  }];

  $.plot("#hoze-bar-chart", d, p);

  var m = null;
  var g = null;
  $("#hoze-bar-chart").bind("plothover", function(e, t, n) {
    if (n) {
      if ($(document).width() >= 1024 && $(document).width() < 1680)
        $("#hoze-bar-chart .flot-x-axis .flot-tick-label:eq(" + n.dataIndex + ")").show();

      var r = n.datapoint[1] - n.datapoint[2];
      if (m != n.series.label || r != g) {
        m = n.series.label;
        g = r;

        if ($(document).width() >= 1024 && $(document).width() < 1680)
          $("#hoze-bar-chart .flot-x-axis .flot-tick-label:eq(" + n.dataIndex + ")").hide();

        $("#tooltip").remove();
        v(n.pageX, n.pageY, r + " " + n.series.label);
      }

      //Free Memory
      r = null;

    } else {
      if ($(document).width() >= 1024 && $(document).width() < 1680)
        $("#hoze-bar-chart .flot-x-axis .flot-tick-label").hide();
      $("#tooltip").remove();
    }
  })

  //Free Memory
  e = null;
  n = null;
  h = null;
  displaycount.e = null;
  displaycount.n = null;
  displaycount.h = null;
  displaycount.totalTitle = null;
  displaycount.offlineTitle = null;
  p = null;
  d = null;
  m = null;
  g = null
};

首先调用图表函数的 JS,每 10 秒调用一次:

var Dashboard = function() {
    "use strict";
    return {
        init: function() {
            handleStackedChart();
            handleLiveUpdatedChart();
        }
    }
}()

var handleLiveUpdatedChart = function() {
    "use strict";
    var listenerAjaxRequest = {};
    listenerAjaxRequest.readyState = 4;
    function e() {
        if( listenerAjaxRequest.readyState != 1)
        {
            listenerAjaxRequest = $.ajax({
                type: "get",
                url: "PHP_FILE_PATH",
                cache: false,
                dataType: "json",
                success: function (response) {
                    displaycount.h = response.displyCountArray.titleData;
                    displaycount.e = response.displyCountArray.onlineData;
                    displaycount.n = response.displyCountArray.offlineData;
                    handleStackedChart();

                    displaycount.h = null;
                    displaycount.e = null;
                    displaycount.n = null;
                }
            });
        }
    }
};

我第一次运行这个网站浏览器获得 235MB 内存,但 10 分钟后我看到浏览器获得 255MB 内存,这个页面每天打开 12 小时并且浏览器崩溃,因为我在页面上有 10 个图表,每个 10 分钟浏览器获得 100MB记忆。

如果我评论运行 handleLiveUpdatedChart() 这个问题会解决,但我需要定期更新数据。

此时我需要知道如何处理内存并解决此问题。

【问题讨论】:

  • 每10秒怎么称呼?
  • 所以你每十秒重新绑定一个新的plothover 监听器?难怪他们会积累记忆
  • @A.Wolff 我更新了问题。
  • 一旦任何未决的ajax请求完成,至少不要使用interval而是递归调用超时,请参阅reallifejs.com/brainchunks/repeated-events-timeout-or-interval当然不要一遍又一遍地绑定事件/插件

标签: javascript jquery memory-leaks


【解决方案1】:

您可以做几件事:

  1. handleStackedChart 函数之外定义 v 函数。您不必在每个函数调用上重新定义它。如果v 函数被多次调用,为了生成一个元素,使用DOM APIs 而不是使用jQuery。请注意,函数调用很昂贵。

  2. handleStackedChart 函数之外定义p 对象,并且只更新它的变量属性,例如:p.xaxis.ticks = h;

  3. 您目前正在为每个handleStackedChart 调用的#hoze-bar-chart 添加一个新侦听器。当事件被触发时,元素的所有事件侦听器都会被调用,仅此一项就可能导致浏览器崩溃。此外,您可以缓存$(document).width() 的结果并重复使用它,而不是一次又一次地调用该函数。

  4. 使用setTimeout 函数代替使用间隔。当请求完成并重新绘制图表时,设置一个新的超时时间。

【讨论】:

  • 感谢您的回答,能否请您发送一个示例:“对于生成元素,使用 DOM APIs 而不是使用 jQuery”
  • Khahesh mikonam!您可以使用document.createElement 来创建元素。一次生成所有元素是另一种可以提高性能的选项。
猜你喜欢
  • 2013-04-02
  • 2011-02-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-30
  • 1970-01-01
相关资源
最近更新 更多