使用$ http的AngularJS指令会造成内存泄漏 - .resolve似乎无法正常工作?

时间:2015-04-24 08:57:00

标签: javascript angularjs memory-leaks

我似乎遇到了问题而且我认为我无法看到解决方案,或许有人可以提供帮助...我有一个AngularJS指令,它发出一个$http请求,返回HTML并注入当有内容时我会看到它 - 我知道这不是很好,HTML的返回应该用JSON替换和模板的使用,但是我无法控制从$ http请求返回的内容。该指令采用一些参数/属性来获取正确的内容,并且所有内容似乎都有效。直接通常在我的视图中有7个位置,一个在我的导航中,我使用ng-include添加到我的索引中,在我的页脚中三次使用ng-include添加到我的index.html然后指令出现在我拥有的ng-view标记内,每个视图的标记可以显示0到3次。这是我的HTML

中的指令
<div data-cms-inject data-page-name="homePageContent" data-slot-name="slot1"></div>

这是JS ......

.directive('cmsInject', ['$rootScope', '$q', '$http', function ($rootScope, $q, $http) {
        'use strict';
        return {
            restrict: 'A',
            link: function (scope, element, attrs) {

                var canceller = $q.defer(),
                    cmsPromise = $http({
                    url : 'url/to/feed',
                    timeout: canceller.promise,
                    method: 'POST',
                    data: [{
                    pageName: attrs.pageName,
                    slotName: attrs.slotName
                    }]
                });

                cmsPromise.success(function(data) {

                    var resp = data[0];

                    if(resp.replace(/\s{1,}/,'').replace(/\r?\n|\r/g,'') !== 'null') {
                        element.html(resp);
                    }
                    console.log('new request success');
                    $rootScope.$broadcast('cmsLoaded');
                }).error(function(data) {
                    console.log('new request error', data);

                }) ;

                $rootScope.$on('$locationChangeStart', function () {
                    console.log('$locationChangeStart');
                    canceller.resolve('locationChange');
                });

            }
        };
    }])

现在这似乎工作正常,但是当我在我的应用程序中的视图之间快速导航时,我注意到应用程序似乎很慢,然后崩溃浏览器,因此我们有内存泄漏。起初我认为这是由于挂起的$ http呼叫,但当我尝试使用超时和&#39; $ locationChangeStart&#39;来解决这些问题时。事件仍然存在。然后我尝试写入控制台,看看会发生什么......这是我的输出......

这是当我加载应用程序时,我们有7个指令实例,3个在ng-view中,4个在ng-includes中

7 new request success

然后切换到没有指令的新视图

7 $locationChangeStart

然后我导航回原始视图

7 $locationChangeStart
3 new request success

我再一次切换到没有指令的新视图

10 $locationChangeStart

我导航回原始视图

10 $locationChangeStart
3 new request success

我再一次切换到没有指令的新视图

13 $locationChangeStart

最后回到原始视图

13 $locationChangeStart
3  new request success

有些事情很奇怪,因为$ locationChangeStart事件被调用的次数增加,比指令在页面中显示的次数多,ng-include + ng-view可以让任何人看到我在这里做错了,一些drectives被遗忘在内存/ DOM我猜?

3 个答案:

答案 0 :(得分:4)

可以解释越来越多的事件处理程序:

$rootScope.$on('$locationChangeStart'

您将事件处理程序附加到$rootScope,当然,当指令的生命周期结束时,它不会消失。事件处理程序应该附加到scope

答案 1 :(得分:1)

您的指令在DOM和js对象之间创建循环引用。尽量避免将事件绑定到rootScope并在指令链接函数中使用$ http等服务。更好的解决方案是将此逻辑放在模块运行功能中。

类似的东西:

.run(['$rootScope', 'myService',  function($rootScope, myService){

    $rootScope.$on('$locationChangeStart', function () {
       myService.doSomethng().then(function(data){
            var resp = data[0];
            if(resp.replace(/\s{1,}/,'').replace(/\r?\n|\r/g,'') !== 'null') {
               $rootScope.$broadcast('cmsLoaded', data);
            }
       });
    });

}])
.directive('cmsInject', ['$rootScope', '$q', '$http', function ($rootScope, $q, $http) {
        'use strict';
        return {
            restrict: 'A',
            link: function (scope, element, attrs) {
               scope.$on('cmsLoaded', function(e, args) {
                    element.html(args);                    
               })
            }
        }
     }])

答案 2 :(得分:1)

将您的http调用移至某些服务,并在您的指令中使用该服务。听取'$ destory'指令事件并尽可能清理。