Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I invoke a function after two or more $scope events have been received?

Tags:

angularjs

For example, let's assume I need to run a function after receiving two events "eventA" and "eventB". What I usually do is to declare for each event a boolean variable, set the variable to true when the event is received, and ask if the other variable is true to run the function:

var a = false, 
    b = false;

$scope.$on("eventA", function(){
    a = true;
    if (b)
        performTask();
});

$scope.$on("eventB", function(){
    b = true;
    if (a)
        performTask();
});

var performTask = function() {
    /* do something... */
};

This gets more complex if there are three or more events. Is there a design pattern to handle these cases?

like image 647
ps0604 Avatar asked Dec 18 '14 02:12

ps0604


2 Answers

You can use $q promises.

var dfdATask= $q.defer();
var dfdBTask= $q.defer();

$scope.$on("eventA", function(){
    // whatever this function does
    dfdATask.resolve(true);//or pass a value
});

$scope.$on("eventB", function(){
    //whatever this function does
    dfdBTask.resolve(true);//or pass a value
});

$q.all([dfdATask.promise, dfdBTask.promise]).then(function(){
    //be sure to pass in an array of promises
    //perform task
})
like image 60
joseph.l.hunsaker Avatar answered Sep 30 '22 20:09

joseph.l.hunsaker


So theory wise if you only want to execute this magical action after you've received these two events have been called at least once then you probably want to use promises.

app.controller('ExampleOneController', [
    '$log',
    '$scope',
    '$q',
    '$rootScope',

    function ($log, $scope, $q, $rootScope) {
        $scope.anotherAction1FiredCount = 0;

        var aDeferred = $q.defer(),
            bDeferred = $q.defer();

        $scope.$on('e-1-a', function () {
            $log.log('Fired e-1-a');
            aDeferred.resolve();
        });

        $scope.$on('e-1-b', function () {
            $log.log('Fired e-1-b');
            bDeferred.resolve();
        });

        $q.all([aDeferred.promise, bDeferred.promise]).then(function () {
            $log.log('Fired another action 1!');
            $scope.anotherAction1 = 'Hello World 1!';

            $scope.anotherAction1FiredCount++;
        });
    }
]);

That being said usually I want to execute everytime two things happen so I tend to 'reset' my promises.

app.controller('ExampleTwoController', [
    '$log',
    '$scope',
    '$q',

    function ($log, $scope, $q) {
        $scope.anotherAction2FiredCount = 0;

        var aDeferred = $q.defer(),
            bDeferred = $q.defer();

        $scope.$on('e-2-a', function () {
            $log.log('Fired e-2-a');
            aDeferred.resolve();
        });

        $scope.$on('e-2-b', function () {
            $log.log('Fired e-2-b');
            bDeferred.resolve();
        });

        var wait = function () {
            $q.all([aDeferred.promise, bDeferred.promise]).then(function () {
                $log.log('Fired another action 2!');
                $scope.anotherAction2 = 'Hello World 2!';
                $scope.anotherAction2FiredCount++;

                aDeferred = $q.defer();
                bDeferred = $q.defer();
                wait();
            });
        };
        wait();
    }
]);

Here's the working plunker!

Promises are life.

like image 36
Nate-Wilkins Avatar answered Sep 30 '22 20:09

Nate-Wilkins