Search code examples
javascriptangularjsangularjs-serviceangularjs-http

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


Solution

  • 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'};
        });
    }