如何修复此角度内存泄漏?

时间:2015-03-05 13:33:00

标签: angularjs memory-leaks

这是我的js

var app = angular.module('SearchAndResultsApp', ['angularUtils.directives.dirPagination']);
app.controller('SearchAndResultsController', function($location ,$scope, $http){
$scope.fields = [
    { id: 'accountNumber', name: 'Account Number', clicked: false},
    { id: 'pointOfInterestName', name: 'Point Of Interest Name', clicked: true},
    { id: 'address1', name: 'Address 1', clicked: false},
    { id: 'address2', name: 'Address 2', clicked: false},
    { id: 'city', name: 'City', clicked: false},
    { id: 'isostateCode', name: 'ISO State Code', clicked: false},
    { id: 'postalCode', name: 'Postal Code', clicked: false},
    { id: 'phone', name: 'Phone', clicked: false},
    { id: 'fax', name: 'Fax', clicked: false},
    { id: 'website', name: 'Website', clicked: false},
    { id: 'email', name: 'Email', clicked: false},
    { id: 'isocountryCode', name: 'ISO Country Code', clicked: false},
    { id: 'latitude', name: 'Latitude', clicked: false},
    { id: 'longitude', name: 'Longitude', clicked: false}
];

$scope.getSearchState = function() {
    var fields = window.location.hash.substring(1).split("&");
    if (fields.length > 0) {
        return decodeURIComponent(fields[0]);
    } else {
        return '';
    }
};

$scope.getPageState = function() {
    var fields = window.location.hash.substring(1).split("&");
    if (fields.length > 1) {
        return parseInt(fields[1]);
    } else {
        return 1;
    }
};

$scope.noResults = false;
$scope.pointsOfInterest = null;
$scope.loadingQuery = false;
$scope.orderDirection = 'asc';
$scope.glyphDirection = 'glyphicon-triangle-top';
$scope.orderedBy = 'pointOfInterestName';
$scope.previousClicked = $scope.fields[1];
$scope.lowerRange = 0;
$scope.upperRange = 0;
$scope.totalRange = 0;
$scope.currentPage = $scope.getPageState();
$scope.searchString = $scope.getSearchState();
$scope.offset = 'col-sm-offset-4';
$scope.loadingOffset = 'col-sm-offset-1';

$scope.getResultsState = function() {
  return ((($scope.pointsOfInterest == null)||($scope.pointsOfInterest[0] == null)) && ($scope.searchString != ''))
};

$scope.downloadCSV = function(selection) {
    if (selection == 'searched') {
        window.location = 'pointsOfInterest/' + encodeURIComponent($scope.searchString) + '/orderedList/' + $scope.orderedBy + '/' + $scope.orderDirection + '/csv';
    } else if (selection == 'all') {
        if (confirm("This may take some time.")){
            window.location = 'allPointsOfInterest/csv';
        }
    }
};

$scope.updateRanges = function() {
    $scope.searchString = $scope.searchString = $scope.searchString.replace(/\//g,'').replace(/\\/g,'');
    window.location.hash = encodeURIComponent($scope.searchString) + '&' + encodeURIComponent($scope.currentPage);
    if ($scope.pointsOfInterest[0] != null) {
        $scope.lowerRange = ($scope.currentPage - 1) * 20 + 1;
        $scope.totalRange = $scope.pointsOfInterest.length;
        $scope.upperRange = $scope.currentPage * 20;
    } else {
        $scope.lowerRange = 0;
        $scope.totalRange = 0;
        $scope.upperRange = 0;
    }
    if ($scope.upperRange > $scope.totalRange) {
        $scope.upperRange = $scope.totalRange;
    }
};

$scope.updateGlyphs = function(field) {
    $scope.searchString = $scope.searchString = $scope.searchString.replace(/\//g,'').replace(/\\/g,'');
    $scope.orderedBy = field.id;

    if ($scope.previousClicked != null)
        $scope.previousClicked.clicked = false;
    field.clicked = true;

    if ($scope.previousClicked == field) {
        if ($scope.orderDirection == 'asc') {
            $scope.orderDirection = 'desc';
            $scope.glyphDirection = 'glyphicon-triangle-bottom';
        } else {
            $scope.orderDirection = 'asc';
            $scope.glyphDirection = 'glyphicon-triangle-top';
        }
    } else {
         $scope.orderDirection = 'asc';
         $scope.glyphDirection = 'glyphicon-triangle-top';
    }

    $scope.updatePointsOfInterest();

    $scope.previousClicked = field;
};

$scope.updatePointsOfInterest = function() {
    if ($scope.searchString.length != 0) {
        $scope.loadingOffset = '';
        $scope.currentPage = $scope.getPageState();
        $scope.searchString = $scope.searchString.replace(/\//g,'').replace(/\\/g,'');
        window.location.hash = encodeURIComponent($scope.searchString) + '&' + encodeURIComponent($scope.currentPage);
        if ($scope.searchString == '') return;
        $scope.loadingQuery = true;
        $http.get('pointsOfInterest/' + encodeURIComponent($scope.searchString) + '/orderedList/' + $scope.orderedBy + '/' + $scope.orderDirection)
            .success(function(data) {
                $scope.pointsOfInterest = data;
                $scope.loadingQuery = false;
                $scope.loadingOffset = 'col-sm-offset-1';
                $scope.updateRanges();
                $scope.noResults = $scope.getResultsState();
                if ($scope.pointsOfInterest.length > 0) {
                    $scope.offset = '';
                } else {
                    $scope.offset = 'col-sm-offset-4';
                }
            })
            .error(function(data) {
                window.location = 'pointsOfInterest/' + encodeURIComponent($scope.searchString) + '/orderedList/' + $scope.orderedBy + '/' + $scope.orderDirection;
            });
    }
};

window.onhashchange = function() {
    $scope.updatePointsOfInterest();
}
$scope.updatePointsOfInterest();

$scope.gotoUpdatePage = function (accountNumber) {
    window.location.href = 'pointOfInterestEditor/' + accountNumber;
};

$scope.onTextClick = function ($event) {
    $event.target.select();
};
});
app.directive('ngDelay', ['$timeout', function ($timeout) {
return {
    restrict: 'A',
    scope: true,
    compile: function (element, attributes) {
        var expression = attributes['ngChange'];
        if (!expression)
            return;

        var ngModel = attributes['ngModel'];
        if (ngModel) attributes['ngModel'] = '$parent.' + ngModel;
        attributes['ngChange'] = '$$delay.execute()';

        return {
            post: function (scope, element, attributes) {
                scope.$$delay = {
                    expression: expression,
                    delay: scope.$eval(attributes['ngDelay']),
                    execute: function () {
                        var state = scope.$$delay;
                        state.then = Date.now();
                        $timeout(function () {
                            if (Date.now() - state.then >= state.delay)
                                scope.$parent.$eval(expression);
                        }, state.delay);
                    }
                };
            }
        }
    }
};
}]);

通过将$ location添加到控制器,我收到内存泄漏。我想使用$ location而不是window.location。我不确定为什么会导致内存泄漏。任何人都知道为什么以及如何解决它?

编辑:它似乎正在制作无限的请求。仍然不确定如何解决它。

1 个答案:

答案 0 :(得分:1)

首先,$location服务有hash()方法,您可以使用window.location.hash()代替$scope.updatePointsOfInterest()

第二:在控制器负载上调用{get {1}}方法执行http get请求。如果失败则更改网址。更改URL后,将重新加载控制器代码,因此$scope.updatePointsOfInterest()方法会一次又一次地执行。

我不确定为什么会触发$http.error()方法。它可能是任何东西。在开发工具(Chrome)的网络标签中查看您的XHR请求。

如果您的$http.error()方法失败(这意味着错误并且处理得当),而不是修复“无限循环”问题,您可以执行以下操作:
1)要么在控制器加载时没有调用$scope.updatePointsOfInterest() 2)或不更改$http.error()方法

中的网址

如果您使用此updatePointsOfInterest()方法描述您要尝试实现的目标,我将能够帮助您正确地编写它。

此致 阿列克谢