摘要:
在第二次迭代遍历自定义对象的“数组”后,使用ng-repeat进行泄漏,如下所示:
<div ng-repeat="d_sampleObject in mySampleObjects"> {{d_sampleObject.description}} </div>
内存配置文件显示剩余的额外“d_sampleObject”而未取消引用.下面是更多细节(通过控制器和注入服务).在提供的plunkr链接中也进行了简单的演示.任何想法和帮助提前非常感谢!
注意:’mySampleObjects’是以下实例的数组:
ml.MySampleObject = function (id) { this.id = id; this.description = 'this is object #:' + ' '+id; }
细节:
我有一个自定义对象模型,它反映了我们在AngularJS应用程序中使用的业务域对象.我发现当我将一个自定义对象的实例传递给ng-repeat时,会保留一个引用(我认为是Angular)并且内存未被释放.这发生在ng-repeat的第二个’wave'(点击’refresh’)上,因为它再次在其对象数组上进行迭代.此泄漏在我的个人资料测试中公开(在Chrome中). Here是plunkr的一个简短例子.单击“刷新”按钮一次(或更多次)以查看泄漏的额外“d_sampleObject”对象实例(在Chrome配置文件检查中).请注意,’d_sampleObject’名称仅在传递给ng-repeat时使用.我已经包含了下面进一步泄漏的额外对象实例(‘d_sampleObject’)的屏幕截图.为什么会有泄漏?如何避免泄漏?
(注意,我发现如果我不通过对象迭代我的对象集合(JS数组)而是通过原始索引(‘整数’),则没有泄漏.泄漏似乎只发生在我使用作为ng-repeat迭代的结果的对象引用)
简单的HTML:
<!DOCTYPE html> <html ng-app="memoryleak"> <head> <Meta charset="utf-8" /> <title>Memory Leak Test</title> <script>document.write('<base href="' + document.location + '" />');</script> <script data-require="angular.js@1.3.x" src="https://code.angularjs.org/1.3.13/angular.min.js" data-semver="1.3.13"></script> <script src="app.js"></script> <script src="dataservice.js"></script> </head> <body ng-controller="MainCtrl"> <div ng-repeat="d_sampleObject in mySampleObjects"> {{d_sampleObject.description}} </div> <br> <button ng-click="redo()">Number of refreshes: {{numRedos}}!</button> </body> </html>
SIMPLE APP.JS
(function(ml) { var app = angular.module('memoryleak',['servicemodule']); app.controller('MainCtrl',['$scope','dataservice',function($scope,dataservice) { $scope.redo = function () { $scope.numRedos++; $scope.mySampleObjects = dataservice.myObjectCollection; dataservice.redo(); } $scope.redo(); }]); }(window.MEMLEAK = window.MEMLEAK || {}));
SIMPLE dataservice.js
(function(ml) { 'use strict'; var serviceModule = angular.module('servicemodule',[]); serviceModule.factory('dataservice',['$rootScope','$http',function ($rootScope,$http) { this.myObjectCollection = []; this.redo = function () { this.numRedos++; // that.myObjectCollection = []; this.myObjectCollection.length = 0; for (var i = 0; i < 10; i++) { var sampleObject = new ml.MySampleObject(i); that.myObjectCollection.push(sampleObject); } sampleObject=null; } ml.MySampleObject = function (id) { this.id = id; this.description = 'this is object #:' + ' '+id; } return this; //return the entire service to make methods accessible to dependents }]); }(window.MEMLEAK = window.MEMLEAK || {}));
屏幕截图1 :(第一页加载 – 创建了10个’mySampleObjects’)
屏幕截图2 :(点击刷新 – 创建/泄漏了第11个mySampleObject,引用了传递给ng-repeat的’d_sampleObject’实例名称.)