r3plica
r3plica

Reputation: 13367

Return a value from a self executed promise in angularJS

I am building a fairly complex service with lots of models and functions. Part of the service looks like this:

// Sports model
var sports = {
    list: function () {

        // Create our deferred promise
        var deferred = $q.defer();

        // Get our categories
        moltin.categories.list(0, 0).then(function (response) {

            // Create our list
            list = [];

            // Loop 6 times
            for (var i = 0; i < 6; i++) {

                // Get our column index
                var colIndex = i + 1;

                // Return our spliced array
                list.push(response.splice(0, 7));
            }

            // Resolve our list
            deferred.resolve(list);
        });

        // Return our promise
        return deferred.promise;
    }()
};

which is then assigned to the service and returned like this:

var service = {
    sports: sports
}

return service;

Now, as you can see I am calling an API (moltin is another service which returns a promise). In my controller I want to do this:

self.list = service.sports.list

Because the method is self executing I expected to actually have a list of categories, but instead I just get the promise. Does anyone know how I can get the list without having to do this:

service.sports.list().then(function (response) {
    self.list = response;
});

Upvotes: 0

Views: 504

Answers (2)

zszep
zszep

Reputation: 4458

You can't, but if this code is in your controller and you're using ng-route or ui-router you have a resolve method on the router that prevents the controller to be called before the promise is resolved, so you can have this in the router:

.when("/news", {
    templateUrl: "newsView.html",
    controller: "newsController",
    resolve: {
        initialData: function(newsControllerInitialData){
            return newsControllerInitialData();
        }
    }
})

and in the controller:

app.controller("newsController", function ($scope, initialData) {
    $scope.message = initialData.message;
    $scope.greeting = initialData.greeting;
});

Upvotes: 0

Jamiec
Jamiec

Reputation: 136074

No, that method is asynchronous, so there is no way to access it without chaining on to the promise.

As an aside, there is a little antipattern in your code too. You should not create a new deferred and return that - you should just return the list from your internal call back and return directly from the method:

var sports = {
    list: function () {

        // Get our categories
        return moltin.categories.list(0, 0).then(function (response) {

            // Create our list
            list = [];

            // Loop 6 times
            for (var i = 0; i < 6; i++) {

                // Get our column index
                var colIndex = i + 1;

                // Return our spliced array
                list.push(response.splice(0, 7));
            }

            return list;
        });

    }()
};

All other code remains the same.

Upvotes: 1

Related Questions