creating a service in angularJS, using restangular promises

Issue

Ok, this is driving me mad, basically what I am trying to do is create a service to get and evaluate user capabilities, I am using WP REST API. I use restangular to get my JSON data.

At this stage I am testing the function in the controller itself, but no matter where I test it, be it in my custom service using this.method or inside the controller, with or without using $scope the result is always undefined. I know I am missing something either in the way I am returning true or false inside the function, or there is something fundamentally different when it comes to promises in JS. Here is the code:

    var current_user = parseInt(o2_i18n.user_id),
        currentUserCapabilities,
        capability;

    $scope.currentUserCan = function(capability) {
        if(current_user !== '0') {
            wpAPIResource.one('users').get()
            .then(function(allUsers){
                for (var i = 0; i < allUsers.length; i++) {
                    if ( allUsers[i].id === current_user ) {
                        var currentUserCapabilities = allUsers[i].capabilities;
                        for(var prop in currentUserCapabilities){
                            if (capability === prop) {
                                //$log.log( prop );
                                return prop;
                            } else {
                                //$log.log( prop );
                                return false;
                            }
                        }
                    }
                }
            }, function(reason){
                $log.error(reason);
            });
        } else {
            //The user is not logged in, therefor no capabilities
            return false;
        }
    };

    $log.log($scope.currentUserCan('publish_posts'));

    if ( $scope.currentUserCan('publish_posts') ) {
        $log.log( 'Yes I Can!' );
    } else {
        $log.warn('No Can\'t Do!');
    }

Solution

Your currentUserCan function doesn’t return anything if current_user !== '0'. You should have it return a promise, for example (for the following you’ll need to inject the $q service)

$scope.currentUserCan = function(capability) {
    if(current_user !== '0') {
        // note the "return" here
        return wpAPIResource.one('users').get().then(function(allUsers){
            for (var i = 0; i < allUsers.length; i++) {
                if ( allUsers[i].id === current_user ) {
                    var currentUserCapabilities = allUsers[i].capabilities;
                    for(var prop in currentUserCapabilities){
                        if (capability === prop) {
                            return prop;
                        }
                    }
                }
            }
            return false;
        }, function(reason){
            $log.error(reason);
            return $q.reject(reason); // you still want the promise to fail
        });
    } else {
        return $q.resolve(false);
        // this turns the static value into a promise so the API for this
        // function is consistent
    }
};

then consume the function like this

$scope.currentUserCan('publish_posts').then(function(can) {
    if (can) {
        $log.log('Yes I Can!');
    } else {
        $log.warn("No Can't Do!");
    }
});

I also cleaned up your loop a little. In your OP, there was no point in the inner loop and you didn’t have a return value if the user was not found in the allUsers array.

Answered By – Phil

Answer Checked By – Senaida (AngularFixing Volunteer)

Leave a Reply

Your email address will not be published.