Search code examples
javascriptangularjsangularjs-scope

How does $scope.$on work and $destroy get invoked?


Can anyone please explain about the working of $scope.$on and how does $destroy work in these two controllers. Like when I change the route, a different controller gets called, is that why $destroy gets invoked? And how does the $interval get initialized, i have just defined it as a variable under promiseA, yet it gets initialized. I just copied these lines to fulfill the requirement, can anyone please help me understand these lines of codes?

        var myApp=angular.module('myApp',['ngRoute']);
        myApp.controller('myController',function($scope){


        });
        myApp.controller('firstPage',function($scope,$interval){

            $scope.thisMessage="First Message";
            $scope.firstcall=function(){
                var promiseA=$interval(function(){

                        console.log("First Page");
                    },10000);
                $scope.$on('$destroy',function(){
                    $interval.cancel(promiseA);
                });
            }
            });
        myApp.controller('secondPage',function($scope,$interval){
            $scope.thisMessage="Second Message";

            $scope.thisMessage="Second Message";
            $scope.secondcall=function(){
                var promiseB=$interval(function(){

                        console.log("Second Page");

                },10000);
                $scope.$on('$destroy',function(){
                    $interval.cancel(promiseB);
                });
            }
        });

        myApp.config(function($routeProvider){
            $routeProvider.when("/",{
                templateUrl:"First.html"
                })
            .when("/second",{
                templateUrl:"Second.html"
            });
        });

Solution

  • Long story short using $scope.$on you can add listeners (subscribe) for angular's internal events and also custom events which you can trigger yourself using the $emit and $broadcast services. The $destroy itself is an event which gets triggered when a controller is being destroyed, so you have a hook if you maybe want to save some data or whatever you'd like to do.

    You can find more information about this kind of stuff in the Angular's documentation here.

    Given the fact that each of your route has a different controller when you are switching through the routes you are instantiating one and destroying the other (which triggers the $destroy event which you are listening for).

    I also recommend you check out $off method, which is the way you can unsubscribe from the events, avoiding memory leaks and strange behaviour. Unfortunately I couldn't find any docs about that but how it basically works is, you subscribe for an event like this:

    $scope.$on('customEvent', someFunction);
    

    And you unsubscribe like this:

    $scope.$on('$destroy', function() {
        $scope.$off('customEvent', someFunction);
    });
    

    Keep in mind that you do not really have to unsubscribe inside the $destroy listener but I think it's a best practice to do so.