LJ Wadowski
LJ Wadowski

Reputation: 6720

Why angular doesn't destroy controllers $scope after route was changed?

I am trying to understand how angular manages the $scopes?

I was sure that if you have controller defined in the routes after route change it should destroy scope controller.

However, it seems that $scope is still in the memory.

My controller Looks like that:

(function () {
    "use strict";
    angular.module('npApp')
            .controller('NpLoginStep1Ctrl', ['$scope', 'NpForms', ... , function ($scope, NpForms, ...) {     
                    /* TEST ONLY - ADD CONTROLLER NAME */
                    $scope.ctrlName = 'step 1';

                    /* ... */

                    /* SERVICE FOR BINDING FORM SUBMISSION */
                    NpForms(this, $scope, 'loginFormStep1'); // ctrl, scope, form name,               
                    /* CONSOLE LOG MESSAGE WHEN SCOPE DESTROY TRIGGERED */
                    $scope.$on('$destroy', function(){
                        console.log($scope.ctrlName);
                        console.log('angular says that scope will be destroyed');
                    });
                }]);
})();

And my service (I know that I can use promises instead passing reference $scope but is not a question here):

.factory('NpForms', ['$http', 'NpSerializeForm', 'NpAlerts', 'NpPreloader', '$timeout', function NpFormsFactory($http, NpSerializeForm, NpAlerts, NpPreloader, $timeout) {
        /* ... */
        return function (ctrl, $scope, form_name) {

            /* ... */

            ctrl.submit = function (form_name, url, redirectUrl) { // redirect url is optional url to redirect the page after form submition is succesfull
                /* ... */

                $http({
                    method: 'POST',
                    url: url,
                    data: NpSerializeForm($scope.npFormData[form_name])
                }).success(function (data) {
                    if (data.status === 0 && data.error) {
                       /* ... */
                    }
                    if (data.validation_error) {
                        /* ... */
                    }

                    /* IF RESPONSE CONTAINS DATA */
                    if (data.response) {
                        if (data.response.data) {
                            /* IF CONTAIN ADDITIONAL DATA TO SCOPE */
                            /* ... */
                        }
                        if (data.response.redirect) {

                            /* WE CHANGE ROUTE HERE AND CONTROLLER SHOULD BE UNLOADED */
                            window.location.hash = data.response.redirect;

                            /* WILL SCOPE DATA BE DELETED? */

                            $timeout(function(){
                                console.log($scope.ctrlName, $scope);
                            }, 5000);
                            return;
                        }

                    }                                                     
                }).error(function () {
                    /* ... */
                });
            };
        };
    }])

And that is what I see in the console after whole process:

And that is what I see in the console after whole process

It seams that after 5 seconds of $timeout after route was changed and $destroyevent fired scope is still there and I can access ctrlName name property. How it is possible?

Upvotes: 3

Views: 2454

Answers (1)

Salasar
Salasar

Reputation: 136

This is javascript garbage collection. You call your factory before destroying $scope and in factory you init $timeout. Memory keep the link of the $scope in factory and after $timeout will be resolved, garbage collector must delete this link and $scope object will be completely destroyed.

Upvotes: 2

Related Questions