【问题标题】:Memory Leak with $timeout in AngularjsAngularjs 中的 $timeout 导致内存泄漏
【发布时间】:2018-04-19 18:40:45
【问题描述】:

我注意到当我在 angularjs 应用程序中使用 $timeout 函数时出现大量内存泄漏,我需要帮助找出原因!

这是一个相对较大的应用程序,它有多个层。

控制器 A 是主控制器。访问几个根范围变量并向数据库发出一些服务请求。这一切似乎工作正常。控制器 A 的模板有一个 ui-view。此 ui-view 可以显示控制器 C、D 或 E。

控制器 C、D 和 E 做类似的事情,但不包含超时功能。

我注意到随着时间的推移,它会爆炸,最终导致浏览器死机。不知何故,我没有正确地破坏东西,我不确定如何。请帮忙!!

如果您需要更多详细信息,请告诉我!

控制器 A:

defaultApp.controller("controllerA", function (ConfigClass, $scope, $log, $timeout,
$state,  utilityServices, dataReadingService) {
try {
    //initial variable
     //initial variable
    $scope.caplLineupCoilCnt = 0;
    $scope.caplLineupCoilTotalLength = 0;
    $scope.error = "";
    $scope.activeTab = sessionStorage.caplLineupActiveTabName == undefined ? 0 : sessionStorage.caplLineupActiveTabName;
    $rootScope.showRunnableConnections = false;
    $scope.Refreshing = false;
    $scope.$parent.GetCraneStatus();

    $scope.changeStringerView = function () {
        $rootScope.caplStringerView = !$rootScope.caplStringerView;
    }

    //assign default filter value
    $scope.caplViewFilter = localStorage.caplViewFilter == undefined ? '4' : localStorage.caplViewFilter;

    //Get rewrap status.
    dataReadingService.getCaplWrapStatus().then(function (results) {
        if (results[0][1] != undefined) {
            $scope.wrapStatusTime = new Date(results[0][1]).getTime();
        }

        if (results[0][0] == "0") {
            $scope.reWrap = "Off";
        }
        else if (results[0][0] == "1") {
            $scope.reWrap = "On";
        }
        else if (results[0][0].toString() == "2") {
            $scope.reWrap = "No Go";
        }
        $scope.eskidCoils = results[1];
        $scope.rewraps = results[2];
    });

    dataReadingService.getWestFullStatus().then(function (results) {
        var resultDate = new Date(results);
        var old = new  Date(1972,1);
        if (resultDate > old) {
            $scope.fullWest = results;
        }
    });


    $scope.togglePopover = function (popup) {
        var popupElement = document.getElementById(popup);
        popupElement.classList.toggle("show");
    };

    //assign active tab and write to session storage
    $scope.assignActiveTab = function (tabIdx) {
        $scope.activeTab = tabIdx;
        sessionStorage.caplLineupActiveTabName = tabIdx;
    };

    //filter columns
    $scope.updateFilterSetting = function (idx) {
        localStorage.caplViewFilter = idx;
    };

    $scope.showRunnableOptions = function () {
        $rootScope.showRunnableConnections = !$rootScope.showRunnableConnections
    }

    //read empty bins, CAPL lineup cnt, CAPL lineup total length
    dataReadingService.getCaplEmptyBins()
        .then(function (result) {
            $scope.emptyBins = result;
        }, function (excp) {
            $scope.error += excp.data.Message + ' | ';
            $log.error(excp.data.Message);
        });
    dataReadingService.getEmptyBins("tek")
        .then(function(results){
            $scope.emptyBinsTek = results;
        },function(excp){
            $scope.error += excp.data.Message + ' | ';
            $log.error(excp.data.Message);
        });
    dataReadingService.getCaplLineupCoilCntAndTotalLength()
        .then(function (result) {
            $scope.caplLineupCoilCnt += result[0];
            $scope.caplLineupCoilTotalLength += result[1];
        }, function (excp) {
            $scope.error += excp.data.Message + ' | ';
            $log.error(excp.data.Message);
        });
    dataReadingService.getCaplRunnableCoilCnt()
        .then(function (result) {
            $scope.caplRunnableCoilCnt = result;
        }, function (excp) {
            $scope.error += excp.data.Message + ' | ';
            $log.error(excp.data.Message);
        });
    dataReadingService.getCaplNonRunnableCoilCnt()
        .then(function (result) {
            $scope.caplNonRunnableCoilCnt = result;
        }, function (excp) {
            $scope.error += excp.data.Message + ' | ';
            $log.error(excp.data.Message);
        });
    dataReadingService.getCaplStringerCoilCnt()
        .then(function (result) {
            $scope.caplStringerCoilCnt = result;
        }, function (excp) {
            $scope.error += excp.data.Message + ' | ';
            $log.error(excp.data.Message);
        });


    var getNoSteelStatus = function () {
        dataReadingService.getNoSteelStatus().then(function (results) {
            $scope.noSteelStatus = results;
        });
        dataReadingService.getCommitsNoSteel().then(function (results) {
            $scope.noSteelCommits = results;
        });

    };
    getNoSteelStatus();

    $scope.commit = function (selection) {
        dataReadingService.commitNoSteel(selection).then(function (results) {
            getNoSteelStatus();
        });
    }

    $scope.orphanize = function (coilNo) {
        $scope.success = false;
        $scope.failure = false;
        dataReadingService.orphanizeCoil(coilNo).then(function (results) {
            if (results == "Success") {
                $scope.success = true;
            }
            else {
                $scope.failure = true;
                $scope.orphanHover = results;
            }

        });
    };

    $scope.TestRunLUMessage = function () {
        dataReadingService.TestRunLUMessage().then(function (results) {

        });
    };


    $scope.ExportToExcel = function () {
        dataReadingService.ExportToExcel().then(function (results) {
            return true;
        });

    }


    var TOFunction = function () {
        if ($state.current.name.substring(5, 9) === 'capl') {
            $state.reload();
            $scope.Refreshing = true;
        }
    }


    $scope.$on('$destroy', function () {
        console.log("State Destroyed");
        $timeout.cancel(timeout);
        console.log("Timeout Canceled");
    });



    //refresh state
    var timeout = $timeout(TOFunction, 15000);    //Usually 5 minutes but reduced to 15 seconds for testing.
} catch (excp) {
    $scope.error += excp + ' | ';
    $log.error(excp);
}
});

更新:

我更改了代码以取消超时。但是在页面上停留一分钟会将 Chrome 任务管理器中的内存从 160mb 移动到 630mb。我还是做错了什么吗?

【问题讨论】:

  • 尝试使用分析器。您还应该清除销毁超时。

标签: javascript angularjs memory-leaks


【解决方案1】:

在调用超时之前更改路由时,计时器仍在运行,这会创建一个闭包,阻止垃圾收集器释放视图的内存。

$destroy事件广播时需要清除超时使用$timeout.cancel()

var timeout;

$scope.$on('$destroy', function() {
  $timeout.cancel(timeout)
});

timeout = $timeout($scope.TimeOut, 15000);

【讨论】:

  • 这可能适用于切换标签,但当我只是坐在页面上时似乎没有帮助。检查我的更新。我是不是做错了什么?
  • 代码中唯一的事情是超时,这被清除了。您可以尝试的其他事情是取消待处理的 API 请求。尝试通过删除元素和/或使用分析器将问题限制在单个控制器上。
  • 我添加了完整的控制器代码。也许这会有所帮助?
猜你喜欢
  • 2015-07-06
  • 2014-06-07
  • 2013-11-20
  • 2011-10-28
  • 2016-01-18
  • 2012-12-13
  • 1970-01-01
  • 2011-01-08
  • 2011-02-01
相关资源
最近更新 更多