AngularJS 带有 $http 的指令会造成内存泄漏 - .resolve 似乎不起作用?

AngularJS directive with $http creates memory leak - .resolve doesn't seem to work?

我似乎遇到了问题,但我认为我看不到解决方案,也许有人可以提供帮助...我有一个 AngularJS 指令,它使 $http 请求 returns HTML 并且当有内容时我将它注入我的视图 - 我知道这不是很好并且 HTML 的返回应该替换为 JSON 和使用模板,但我无法控制 $http 请求返回的内容。该指令需要一些 arguments/attributes 才能获得正确的内容,并且一切似乎都有效。在我看来,直接通常在 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 调用引起的,但是当我尝试使用超时和“$locationChangeStart”事件解决这些问题时,问题仍然存在。然后我尝试写入控制台以查看会发生什么...这是我的输出...

这是当我加载应用程序时,我们有 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 谁能看出我在这里做错了什么,我猜 memory/DOM 中遗留了一些指令?

事件处理程序数量的增加可以解释为:

$rootScope.$on('$locationChangeStart'

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

您的指令在 DOM 和 js 对象之间创建了循环引用。尽量避免将事件绑定到 rootScope 并在指令 link 函数中使用 $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);                    
               })
            }
        }
     }])

将您的 http 调用移至某个服务并在您的指令中使用该服务。监听指令的“$destory”事件,如果可以的话做一些清理工作。