noobcoder
noobcoder

Reputation: 12801

AngularJS TypeError: "track" is not a function

I am trying to call a service with parameters from my controller method and I get an error saying that it is not a function. Here is my code:

(function (){

angular.module('app.uploadedReleases')
        .controller('UploadedReleasesController', UploadedReleasesController)
        .controller('ModalController', ModalController);


UploadedReleasesController.$inject = ['$log', '$scope', '$modal', 'ReleaseService', 'TrackService'];
function UploadedReleasesController ($log, $scope, $modal, releaseService, trackService){

        vm.selectTrack = selectTrack;

       function selectTrack(album, track, index){

        trackService.currentTrack(album.slug, track.fileName).then(function(responseValue){
            vm.temp = responseValue;
        });
        vm.formTrack = vm.selected.track;
    }
}

Here is my service called trackService:

angular.module('app.services')
        .service('TrackService', TrackService);

TrackService.$inject = ['$http', '$q'];

function TrackService($http, $q){
    var trackService = {};

    var releasesUrl = 'http://localhost:8080/api/releases';
    trackService.currentTrack = currentTrack;

        function currentTrack(releaseSlug, trackSlug){
        var trackUrl = releasesUrl + '/'+ releaseSlug + '/' + trackSlug + '/track';
        var deferred = $q.defer();

        $http.get(trackUrl).then(function(trackResponse){
            return deferred.resolve(trackResponse);
        }, function(error){
            return deferred.reject({msg: 'Error while getting the current track details'})
        });
      return deferred.promise;
    }
}

Any idea why I would get the error in my controller: TypeError: trackService.currentTrack is not a function

Upvotes: 1

Views: 1274

Answers (2)

Pankaj Parkar
Pankaj Parkar

Reputation: 136144

Very 1st thing I'd say that is, you are creating a service then you should bind method to this context, rather creating object.

var trackService = {};

would change to

var trackService = this;

But returning custom object from service isn't wrong also. So in current situation you missed to returned it. At the end of your service code to add

return trackService 

Still confused how service & factory work, I'd recommend to readup on this answer


You should return a promise from trackService.currentTrack method which you had created in custom way.

trackService.currentTrack = currentTrack;
function currentTrack(releaseSlug, trackSlug){
    var trackUrl = releasesUrl + '/'+ releaseSlug + '/' + trackSlug + '/track';
    var deferred = $q.defer();
    $http.get(trackUrl).then(function(trackResponse){
        return deferred.resolve(trackResponse);
    }, function(error){
        return deferred.reject({msg: 'Error while getting the current track details'})
    });
    return deferred.promise; //returned promise
}

Rather you should be do your custom promise which is consider as anti-pattern to implement where you have promise returned by $http.get method, You should utilize that.

Refactored Version

trackService.currentTrack = currentTrack;
    function currentTrack(releaseSlug, trackSlug){
    var trackUrl = releasesUrl + '/'+ releaseSlug + '/' + trackSlug + '/track';
    return $http.get(trackUrl).then(function(trackResponse){
        return trackResponse;
    }, function(error){
        return {msg: 'Error while getting the current track details'};
    });
}

Upvotes: 1

nickgraef
nickgraef

Reputation: 2417

@Pankaj Parkar's answer is correct in that you should be returning a promise from currentTrack in order to chain then in your controller.

However, to answer your question about the TypeError, you're mixing factory and service syntax here in TrackService.

To make it a factory, return a map of the exposed functions:

function TrackService($http, $q){
    var trackService = {};
    trackService.currentTrack = currentTrack;

    function currentTrack(releaseSlug, trackSlug){
        //...
    }

    return trackService;
}

and declare with .factory('TrackService', TrackService);.

To make it a service, add the exposed functions to this:

function TrackService($http, $q){
    this.currentTrack = currentTrack;

    function currentTrack(releaseSlug, trackSlug){
        //...
    }
}

and declare with .service('TrackService', TrackService);.

Upvotes: 3

Related Questions