为什么/我的代码如何导致内存泄漏?

时间:2017-03-22 13:56:33

标签: javascript memory-leaks setinterval spotfire

我在Spotfire TextArea中编写了以下JavaScipt代码。我包含应用程序和标记的完整性,但我不认为我的问题是特定于Spotfire的。基本上,我有一个每5分钟运行一次的计时器,并点击一个链接(clickLink('Foo');)来触发应用程序中其他地方的某些Python代码的执行。如果应用程序还包含上次完整更新的时间戳,该时间戳以相同的方式每隔30分钟发生一次(clickLink('Foo');):

function reportTimestamp() {
  var timeNow = new Date();
  var hoursNow = timeNow.getHours();
  var minutesNow = timeNow.getMinutes();
  var secondsNow = timeNow.getSeconds();
  return hoursNow + ":" + minutesNow + ":" + secondsNow;
};

function timeBasedReaction(timestampAge){
  if (timestampAge >= 1800) {
    clickLink('Foo');
    clickLink('Bar');
  } else if (timestampAge >= 300) {
    clickLink('Foo');
  };
};
/*
function timeBasedReaction_B(timestampAge){
  if (timestampAge >= 300) {
    clickLink('Foo');
    if (timestampAge >= 1800) {
      clickLink('Bar');
    };
  };
};
*/
function clickLink(linkName) {
  var clickTarget = document.getElementById(linkName).children[0];
  clickTarget.click();
};

function checkTimestampAge() {
  console.log(reportTimestamp());
  var myTimeStamp = document.getElementById('Timestamp').children[0]
  var timeStampMS = new Date(myTimeStamp.textContent).getTime();
  var currentDateMS = new Date().getTime();
  var timestampAgeSeconds = (currentDateMS - timeStampMS)/1000;
  timeBasedReaction(timestampAgeSeconds);
};

function pageInitialization() {
  checkTimestampAge();
  var myTimer = null;
  var timerInterval = 300000;
  myTimer = setInterval(function(){checkTimestampAge()},timerInterval);
}

pageInitialization();

由于我不清楚的原因,在应用程序或Web浏览器中运行此代码启动很好,但最终会导致非常大的内存分配。 我试过读 4 Types of Memory Leaks in JavaScript and How to Get Rid Of ThemJS setInterval/setTimeout Tutorial,和 An interesting kind of JavaScript memory leak,这是一个开始,但我不知道真正理解我做错了什么以及如何纠正它。

谢谢,并抱歉这块巨大的文字。

1 个答案:

答案 0 :(得分:0)

这会导致内存泄漏,因为Spotfire处理与TextArea关联/加载的Javascript的方式。

在桌面客户端以及Webplayer实例中,当加载页面时,加载该页面的所有部分,包括TextArea并包括其中相关的Javascript。我之前在上述评论中的理解是:

"the code is intended to run when the page loads, and it was my understanding that it would stop/be cleared if the page was re-loaded or someone navigated away from it"

不正确。脚本的其中一个操作是更新/重绘TextArea中的HTML位置。反过来,这会重新加载TextArea ,但不会清除现有的Javascript代码。但是,它不再可以访问,因为var myTimer = null实际上创建了一个新的myTimer而不是将现有的myTimer归零。通过这种方式,function timeBasedReaction的实例作为 val scrollView = NestedScrollView(activity) scrollView.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) scrollView.isFillViewport = true val rootLayout = CoordinatorLayout(activity) rootLayout.layoutParams = rootLayout.setDimensions(CoordinatorLayout.LayoutParams.MATCH_PARENT, CoordinatorLayout.LayoutParams.MATCH_PARENT) val tabLayout = TabLayout(activity) tabLayout.tabMode = TabLayout.MODE_FIXED tabLayout.tabGravity = TabLayout.GRAVITY_FILL rootLayout.addView(tabLayout) tabLayout.layoutParams = CoordinatorLayout.LayoutParams(CoordinatorLayout.LayoutParams.MATCH_PARENT, CoordinatorLayout.LayoutParams.WRAP_CONTENT) tabLayout.setBackgroundColor(ContextCompat.getColor(activity, R.color.account_background)) val viewPager = ViewPager(activity) viewPager.id = 11122 viewPager.layoutParams = CoordinatorLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT).apply { behavior = AppBarLayout.ScrollingViewBehavior() } setupViewPager(viewPager, data[0]) rootLayout.addView(viewPager) tabLayout.setupWithViewPager(viewPager) scrollView.addView(rootLayout) return scrollView 的实例在几何上增加并且不断更新基础TextArea并加载更多相同的Javascript。

对于有类似问题的人来到这里,已经超过3个月了,我还没有想出如何一劳永逸地解决这个问题。如果我这样做,我会尝试再次更新。