-1

I am trying to create a dummy exercise to help my colleagues understand AngularJS. In my example I wish to call a service to provide an Object Array that we shall pass into a Controller and assign to a $scope variable (the example I am creating is providing information about the Beatles). I don't want to build a REST service for my examples, so I was just going to return a static / hard coded Object Array from my service. However what I return from the service is not a promise and thus I can't use the .then() method or should I say I get an error when I do try to use it.

TypeError: AlbumsService.fetchBeatlesAlbums(...).then is not a function

As we use .then() when providing data via $http I would like to use .then() so it is similar to a real world app. Is there a way I can simply get round this? Below are my controllers and my service... I have commented where the error occurs:

angular.module('beatlesApp', []) // First we state the app name, followed by an array of dependancies
    // here is our controller...
    .controller('MainCtrl', ['$scope', function($scope) {
        // here we can set our $scope variables
    }])

    .controller('ChildCtrl', ['$scope', 'AlbumsService', function($scope, AlbumsService) {
    // here we can set our $scope variables

        // HERE WE GET AN ERROR... AlbumsService.fetchBeatlesAlbums(...).then is not a function    
        AlbumsService.fetchBeatlesAlbums().then(function(resp) {
            $scope.albums = resp;
        });
    }])

// This is a service that provides data, in a real world app we would get the data from $http sources
.service('AlbumsService', function() {

    this.fetchBeatlesAlbums = function() {
        return [{
            name: 'Please Please Me',
            released: '1963',
            pic: 'please.jpg'
        }, {
            name: 'With the Beatles',
            released: '1963',
            pic: 'with.jpg'
        }, {
            name: 'A Hard Day\' s Night',
            released: '1964',
            pic: 'hard.jpg'
        }, {
            name: 'Beatles For Sale',
            released: '1964',
            pic: 'bfs.jpg'
        }, {
            name: 'Help!',
            released: '1965',
            pic: 'help.jpg'
        }, {
            name: 'Rubber Soul',
            released: '1965',
            pic: 'rubber.jpg'
        }, {
            name: 'Revolver',
            released: '1966',
            pic: 'revolver.jpg'
        }, {
            name: 'Sgt Pepper\'s Lonely Hearts Club Band',
            released: '1967',
            pic: 'splhb.jpg'
        }];
    };
});
Mark Sandman
  • 3,293
  • 12
  • 40
  • 60

2 Answers2

2

This should work fine:

  .service('AlbumsService', function($q) {

    this.fetchBeatlesAlbums = function() {
        var defer = $q.defer();
        var arr = [{
            name: 'Please Please Me',
            released: '1963',
            pic: 'please.jpg'
        }, {
            name: 'With the Beatles',
            released: '1963',
            pic: 'with.jpg'
        }, {
            name: 'A Hard Day\' s Night',
            released: '1964',
            pic: 'hard.jpg'
        }, {
            name: 'Beatles For Sale',
            released: '1964',
            pic: 'bfs.jpg'
        }, {
            name: 'Help!',
            released: '1965',
            pic: 'help.jpg'
        }, {
            name: 'Rubber Soul',
            released: '1965',
            pic: 'rubber.jpg'
        }, {
            name: 'Revolver',
            released: '1966',
            pic: 'revolver.jpg'
        }, {
            name: 'Sgt Pepper\'s Lonely Hearts Club Band',
            released: '1967',
            pic: 'splhb.jpg'
        }];
        defer.resolve(arr)
        return defer.promise;
    };
});
Przemek
  • 803
  • 4
  • 15
2

You can use the $q service in combination with the $timeout service to return a promise to imitate what $http would return.

For example:

.service('AlbumsService', function($q, $timeout) {

    this.fetchBeatlesAlbums = function() {

        var deferred = $q.defer();

        $timeout(function() {
            deferred.resolve([{
                name: 'Please Please Me',
                released: '1963',
                pic: 'please.jpg'
            }, {
                name: 'With the Beatles',
                released: '1963',
                pic: 'with.jpg'
            }, {
                name: 'A Hard Day\' s Night',
                released: '1964',
                pic: 'hard.jpg'
            }, {
                name: 'Beatles For Sale',
                released: '1964',
                pic: 'bfs.jpg'
            }, {
                name: 'Help!',
                released: '1965',
                pic: 'help.jpg'
            }, {
                name: 'Rubber Soul',
                released: '1965',
                pic: 'rubber.jpg'
            }, {
                name: 'Revolver',
                released: '1966',
                pic: 'revolver.jpg'
            }, {
                name: 'Sgt Pepper\'s Lonely Hearts Club Band',
                released: '1967',
                pic: 'splhb.jpg'
            }]);
        }, 1000); //Returns after a 1 second delay.

        return deferred.promise;
    };
});

The advantage of using $timeout with $q over just $q is that you can use it imitate a realistic delay from requesting data from a real service.

Seaal
  • 386
  • 2
  • 6