punkbit
punkbit

Reputation: 7707

Angularjs: Promises

I'm doing some small exercises to learn AngularJS, trying to understand how to work with promises at the moment.

In the following exercise, I'm trying to get some data async. I can see the data in the console.log but the promise is returned NULL.

Anyone experienced can give me some advice to understand what I'm doing wrong ? Thanks for looking!

angular.module('questions', [])

.config(function($routeProvider) {
    $routeProvider
    .when('/', {
        controller: 'MainCtrl',
        resolve: {
            'MyServiceData': function(EntriesService) {
                return EntriesService.promise;
            }
        }
    })
})

.service('EntriesService', function($http) {

    var entries = null;

    var promise = $http.get('entries').success(function (data) {
        entries = data;
    });

    return {
        promise: promise,
        all: function() {
            return entries;
        }
    };
})

.controller('MainCtrl', ['$scope', 'EntriesService', function($scope, EntriesService) {

  console.log('Promise is resolved: ' + EntriesService.all());

  $scope.title = "Q&A Module";

  $scope.entries = EntriesService.all() || [];

  $scope.addMessage = function() {
    $scope.entries.push({
        author: "myAuthor",
        message: $scope.message
    });
  };

}]);

/****** Thanks everyone for your help so far *****/

After taking the advice of @bibs I came up with the following solution, that's clear using ngResource:

angular.module('questions', ['ngResource'])

.factory('EntriesService', function($resource){
  return $resource('/entries', {});
})

.controller('MainCtrl', ['$scope', 'EntriesService', function($scope, EntriesService) {

  $scope.title = "Q&A Module";

  $scope.entries = [];

  EntriesService.query(function(response){
    $scope.entries = response;        
  });

  $scope.addMessage = function() {
    $scope.entries.push({
        author: "myAuthor",
        message: $scope.message
    });
  };

}]);

Upvotes: 0

Views: 432

Answers (2)

zs2020
zs2020

Reputation: 54504

You should access the data in the callback. Since entries maybe empty before the data arrives, the all() function is not quite useful in this case.

Try this, you should be able to chain then() method to synchronously get data.

.service('EntriesService', function ($http) {
    var services = {
        all: function () {
            var promise = $http.get('entries').success(function (data) {
                entries = data;
            }).error(function (response, status, headers, config) {
                //error
            });
            return promise;
        },

        someOtherServices: function(){
            var promise = ....
            return promise;
        }

        return services;
    }
});

$scope.entries = [];
EntriesService.all().then(function(data){
    $scope.entries = data;
});

Upvotes: 1

bibs
bibs

Reputation: 1226

If you want the data returned by the server to be immediately reflected in your view:

.service('EntriesService', function($http) {

    var entries = [];

    var promise = $http.get('entries').success(function (data) {
        for (var i = 0; i < data.length; i++) {
            entries[i] = data[i];
        }
    });

    return {
        promise: promise,
        all: entries
    };
})

.controller('MainCtrl', ['$scope', 'EntriesService', function($scope, EntriesService) {

  $scope.title = "Q&A Module";

  $scope.entries = EntriesService.all;

  $scope.addMessage = function() {
    $scope.entries.push({
        author: "myAuthor",
        message: $scope.message
    });
  };

You may want to check out $resource to do this for you: http://docs.angularjs.org/api/ngResource.$resource

Upvotes: 1

Related Questions