kabrice kabrice - 4 years ago 118
reST (reStructuredText) Question

TypeError: Cannot read property '$promise' of undefined with using ngResource in angularJS

I created a service in my angularJS app with ngResource to send some data to my rest api.

I want to use a promise to perform some tasks with it in my controller just after I sent a request.

Here is my service :

angular.module("MyService", ['ngResource'])

.factory("myService", function ($rootScope, $http, $resource) {

var apiData = $resource(
"/api", {},
{

"postQuestion": { method: "POST", url: "/api/:userid"}

});

return {

postQuestion: function(question, user_id) {
apiData.postQuestion({ userid: user_id}, question, function(data) {
console.log("Sucsess !");
}, function(error) {
console.log("Error " + error.status + " when sending request : " + error.data);
});

}
}
});


And here is how I used it in my controller :

app.controller("MyCtrl", function ($scope, $filter, $http, $sce, myService, ngDialog, $rootScope, $location) {


$scope.postQuestion = function(newQuestion)
{

myService.postQuestion(newQuestion, 1).$promise.then(function(){
$scope.showNewQuestion = false;
$location.path("/");
});
}


})


But when running my app, I got this error in my console :


TypeError: Cannot read property '$promise' of undefined
at Scope.$scope.postQuestion ...


Don't know why, please help

Answer Source

This function in myService isn't returning a promise:

postQuestion: function(question,  user_id) {
    apiData.postQuestion({ userid: user_id}, question, function(data) {
        console.log("Sucsess !");
    }, function(error) {
        console.log("Error " + error.status + " when sending request : " + error.data);
    });
}

yet the calling code in the controller is expecting one:

myService.postQuestion(newQuestion, 1).$promise.then(function(){
    $scope.showNewQuestion = false;
    $location.path("/");
});

To fix you can create your own promise using the $q library, then resolve or reject it as required and then return that promise to the controller:

postQuestion: function(question,  user_id) {
    var deferred = $q.defer();
    apiData.postQuestion({ userid: user_id}, question, function(data) {
        console.log("Sucsess !");
        deferred.resolve(data);
    }, function(error) {
        console.log("Error " + error.status + " when sending request : " + error.data);
        deferred.reject(error);
    });
    return defered.promise;
}

Then you can remove$promise from the calling code and call the then function on the return value of myService.postQuestion(which is now a promise):

myService.postQuestion(newQuestion, 1).then(function(){
    $scope.showNewQuestion = false;
    $location.path("/");
});
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download