草庐IT

javascript - 内存泄漏 : Remaining elements in cache and data_user in AngularJs

coder 2024-07-26 原文

我使用 ng-repeat 创建元素(有些是 SVG 标签,有些是简单的 HTML)。在数据模型发生变化时——一个在新数据到达时重置的对象——总会有元素作为分离的 DOM 元素留下。他们是这样举行的:

元素是 data_user 的一部分,它似乎是 jquery 的一部分。此问题发生在多个更改数据的地方。似乎观察者是问题所在,因为他们一直在引用自己的表情。

元素被创建,例如像这样:

.directive('svgGraphic', ['$compile', function ($compile) {
    return {
        restrict: 'E',
        replace: false,
        link: function (scope, element, attrs) {
            var svgData = scope.model.getAttribute("svgGraphic");
            var svgDomElement =  $(svgData.svg);
            scope.layers = svgData.layers;

            svgDomElement.append('<svg-layer ng-repeat="layer in layers"></svg-layer>');
            element.append($compile(svgDomElement)(scope));

            scope.$on("$destroy", function() {
                scope.$$watchers = null;
                scope.$$listeners = null;
            })
        }
    };
}])

解决方法是手动删除观察者和听众,如上所示 - 我认为这不是好的解决方案!

当来自服务器的新数据到达时,它是这样设置的:

$scope.model = model;
$scope.$digest();

只替换模型数据有问题吗?

是否知道 angular 不会删除旧元素上的监听器是如何发生的?当 ng-repeat 接收到新数据并重建所有元素时,Angular 应该删除所有观察者。

最佳答案

我发现了同样的问题。我创建了一个 Watcher 类,然后使用探查器我可以计算 Watcher 实例。当我浏览应用程序时,我看到实例继续增加,一些实例由 data_user 缓存保留:(。

我还修复了 childScopes 观察器的删除问题,并向范围添加了一些元数据,例如 childScope 列表。

这是我更改的 Angular 代码(只有我更改的功能)。我希望这可以帮助您找到错误,我仍在与它作斗争:)

function $RootScopeProvider() {


 this.$get = ['$injector', '$exceptionHandler', '$parse', '$browser',
  function($injector, $exceptionHandler, $parse, $browser) {

 var watcherCount = 0;

function Watcher(listener, initWatchVal, get, watchExp, objectEquality, scope) {
  this.fn = isFunction(listener) ? listener : noop;
  this.last = initWatchVal;
  this.get = get;
  this.exp = watchExp;
  this.eq = !!objectEquality;
  this.scope = scope;
  this.id = watcherCount++;
}

Watcher.prototype = {
  constructor: Watcher
}

function Scope() {
  this.$id = nextUid();
  this.$$phase = this.$parent = this.$$watchers =
                 this.$$nextSibling = this.$$prevSibling =
                 this.$$childHead = this.$$childTail = null;
  this.$root = this;
  this.$$destroyed = false;
  this.$$listeners = {};
  this.$$listenerCount = {};
  this.$$isolateBindings = null;
  this.childsScopes = [];
}


Scope.prototype = {
  constructor: Scope,

  $new: function(isolate, parent) {
    var child;

    parent = parent || this;

    if (isolate) {
      child = new Scope();
      child.$root = this.$root;
    } else {
      // Only create a child scope class if somebody asks for one,
      // but cache it to allow the VM to optimize lookups.
      if (!this.$$ChildScope) {
        this.$$ChildScope = function ChildScope() {
          this.$$watchers = this.$$nextSibling =
              this.$$childHead = this.$$childTail = null;
          this.$$listeners = {};
          this.$$listenerCount = {};
          this.$id = nextUid();
          this.$$ChildScope = null;
        };
        this.$$ChildScope.prototype = this;
      }
      child = new this.$$ChildScope();
    }
    //window.scopes = window.scopes || {};
    //window.scopes[child.$id] = child;
    this.childsScopes.push(child);
    child.$parent = parent;
    child.$$prevSibling = parent.$$childTail;
    if (parent.$$childHead) {
      parent.$$childTail.$$nextSibling = child;
      parent.$$childTail = child;
    } else {
      parent.$$childHead = parent.$$childTail = child;
    }

    // When the new scope is not isolated or we inherit from `this`, and
    // the parent scope is destroyed, the property `$$destroyed` is inherited
    // prototypically. In all other cases, this property needs to be set
    // when the parent scope is destroyed.
    // The listener needs to be added after the parent is set
    if (isolate || parent != this) child.$on('$destroy', destroyChild);

    return child;

    function destroyChild() {
      child.$$destroyed = true;
      child.$$watchers = null;
      child.$$listeners = {};
      //child.$parent = null;
      child.$$nextSibling = null;
      child.$$childHead = null;
      child.$$childTail = null;
      child.$$prevSibling = null;
      child.$$listenerCount = {};
      if (child.$parent) {
        var index = child.$parent.childsScopes.indexOf(child);
        child.$parent.childsScopes.splice(index, 1);
      }

      console.log("Destroying childScope " + child.$id);

    }
  }

  $destroy: function() {
    // we can't destroy the root scope or a scope that has been already destroyed
    if (this.$$destroyed) return;
    var parent = this.$parent;
    console.log('Destroying Scope '+ this.$id);
    //delete window.scopes[this.$id];
    this.$broadcast('$destroy');
    this.$$destroyed = true;
    if (this === $rootScope) return;

    for (var eventName in this.$$listenerCount) {
      decrementListenerCount(this, this.$$listenerCount[eventName], eventName);
    }

    // sever all the references to parent scopes (after this cleanup, the current scope should
    // not be retained by any of our references and should be eligible for garbage collection)
    if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;
    if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;
    if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;
    if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;

    // Disable listeners, watchers and apply/digest methods
    this.$destroy = this.$digest = this.$apply = this.$evalAsync = this.$applyAsync = noop;
    this.$on = this.$watch = this.$watchGroup = function() { return noop; };
    this.$$listeners = {};

    // All of the code below is bogus code that works around V8's memory leak via optimized code
    // and inline caches.
    //
    // see:
    // - https://code.google.com/p/v8/issues/detail?id=2073#c26
    // - https://github.com/angular/angular.js/issues/6794#issuecomment-38648909
    // - https://github.com/angular/angular.js/issues/1313#issuecomment-10378451

    this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =
        this.$$childTail = this.$root = this.$$watchers = null;
  }


}];
}

关于javascript - 内存泄漏 : Remaining elements in cache and data_user in AngularJs,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25015947/

有关javascript - 内存泄漏 : Remaining elements in cache and data_user in AngularJs的更多相关文章

  1. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  2. ruby-on-rails - Ruby 中的内存模型 - 2

    ruby如何管理内存。例如:如果我们在执行过程中采用C程序,则以下是内存模型。类似于这个ruby如何处理内存。C:__________________|||stack|||------------------||||------------------|||||Heap|||||__________________|||data|__________________|text|__________________Ruby:? 最佳答案 Ruby中没有“内存”这样的东西。Class#allocate分配一个对象并返回该对象。这就是程序

  3. 键删除后 ruby​​ 哈希内存泄漏 - 2

    你好,我无法成功如何在散列中删除key后释放内存。当我从哈希中删除键时,内存不会释放,也不会在手动调用GC.start后释放。当从Hash中删除键并且这些对象在某处泄漏时,这是预期的行为还是GC不释放内存?如何在Ruby中删除Hash中的键并在内存中取消分配它?例子:irb(main):001:0>`ps-orss=-p#{Process.pid}`.to_i=>4748irb(main):002:0>a={}=>{}irb(main):003:0>1000000.times{|i|a[i]="test#{i}"}=>1000000irb(main):004:0>`ps-orss=-p

  4. ruby-on-rails - 使用 javascript 更改数据方法不会更改 ajax 调用用户的什么方法? - 2

    我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的

  5. ruby-on-rails - HTTParty 的内存问题和下载大文件 - 2

    这会导致Ruby出现内存问题吗?我知道如果大小超过10KB,Open-URI会写入TempFile。但是HTTParty会在写入TempFile之前尝试将整个PDF保存到内存吗?src=Tempfile.new("file.pdf")src.binmodesrc.writeHTTParty.get("large_file.pdf").parsed_response 最佳答案 您可以使用Net::HTTP。参见thedocumentation(特别是标题为“流媒体响应机构”的部分)。这是文档中的示例:uri=URI('http://e

  6. ruby - 在 Mechanize 中使用 JavaScript 单击链接 - 2

    我有这个:AccountSummary我想单击该链接,但在使用link_to时出现错误。我试过:bot.click(page.link_with(:href=>/menu_home/))bot.click(page.link_with(:class=>'top_level_active'))bot.click(page.link_with(:href=>/AccountSummary/))我得到的错误是:NoMethodError:nil:NilClass的未定义方法“[]” 最佳答案 那是一个javascript链接。Mechan

  7. javascript - jQuery 的 jquery-1.10.2.min.map 正在触发 404(未找到) - 2

    我看到有关未找到文件min.map的错误消息:GETjQuery'sjquery-1.10.2.min.mapistriggeringa404(NotFound)截图这是从哪里来的? 最佳答案 如果ChromeDevTools报告.map文件的404(可能是jquery-1.10.2.min.map、jquery.min.map或jquery-2.0.3.min.map,但任何事情都可能发生)首先要知道的是,这仅在使用DevTools时才会请求。您的用户不会遇到此404。现在您可以修复此问题或禁用sourcemap功能。修复:获取文

  8. ruby-on-rails - 内存中具有相同 ID 的更多对象? - 2

    在部署在heroku上的Rails应用程序(v:3.1)中,我在内存中获得了更多具有相同ID的对象。我的heroku控制台日志:>>Project.find_all_by_id(92).size=>2>>ActiveRecord::Base.connection.execute('select*fromprojectswhereid=92').to_a.size=>1这怎么可能?可能是什么问题? 最佳答案 解决方案根据您的SQL查询,您的数据库中显然没有重复条目。也许您的类项目中的size或length方法已被覆盖。我试过find_

  9. ruby - rails 3.0.7 内存泄漏 - 2

    我的两个不同的Rails应用程序的内存有一些奇怪的问题。这两个应用程序都使用rails3.0.7。每个Controller请求分配20-30-50MB的内存。在生产模式下,这个数量减少到5-10。但这是同样的事情。这是两个应用程序使用的gem列表:gem'pg'gem'haml'gem'sass'gem'devise'gem'simple_form'gem'state_machine'gem"globalize3","0.1.0.beta"gem"easy_globalize3_accessors"gem'paperclip'gem'andand'关闭所有这些gem不会给我任何结果。我

  10. ruby-on-rails - 我将 Rails3 与 tinymce 一起使用。如何呈现用户关闭浏览器javascript然后输入xss? - 2

    我有一个用Rails3编写的站点。我的帖子模型有一个名为“内容”的文本列。在帖子面板中,html表单使用tinymce将“content”列设置为textarea字段。在首页,因为使用了tinymce,post.html.erb的代码需要用这样的原始方法来实现。.好的,现在如果我关闭浏览器javascript,这个文本区域可以在没有tinymce的情况下输入,也许用户会输入任何xss,比如alert('xss');.我的前台会显示那个警告框。我尝试sanitize(@post.content)在posts_controller中,但sanitize方法将相互过滤tinymce样式。例如

随机推荐