我似乎遇到了问题而且我认为我无法看到解决方案,或许有人可以提供帮助...我有一个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我猜?
答案 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'指令事件并尽可能清理。