1

I am working with the $http in 1.4.7.

I need to separate my controllers from any $http requests. So i created a service as follows:

app.service('MyService', function($http, $q, $rootScope) {

  this.getcustomers = function() {
    var deferred = $q.defer();
    $http({
      method: 'GET',
      url: 'http://call/to/rest/api'
    }).then(function successCallback(response) {
      deferred.resolve(response.data);
    }, function errorCallback(response) {
      deferred.reject(error);
    });
    return deferred.promise;
  };

});

Then in my controller i call that service as follows:

app.controller('registerationCtrl', ['$scope', '$http', 'MyService', '$location', function($scope, $http, MyService, $location) {
  $scope.custlst = [];

  $scope.getcustomers = function() {

    var x = MyService.getcustomers().then(function(data) {
      $scope.custlst = data;
    }, function(err) {
      alert(err);
    });

  }


}]);

Now, the above is not working it gives me a ReferenceError of error now defined and points to the errorCallback function in the service.

Question 1: What is wrong with the script? Question 2: Is it important to use $q? Keeping in mind that the server can be slow.

Thanks.

2
  • error variable inside errorCallback is not defined, hence the error... You probably meant to do function errorCallback(error) {...} instead of function errorCallback(response) {...}. And no, you didn't need to use $q - you could have just returned the promise already generated by $http Commented Oct 10, 2015 at 1:55
  • Yup that fixed it thanks mate Commented Oct 10, 2015 at 2:07

3 Answers 3

3

Actually you don't need to use $q to create a promise. $http do it for you already, so you can simply do :

app.service('MyService', function($http) {
  this.getcustomers = function() {
    return $http.get({
      method: 'GET',
      url: 'http://call/to/rest/api'
    });
  };
});

Then you can chain your MyService.getcustomers with .then() easily and handle the response like that :

MyService.getcustomers.then(
  function(data) {
    //do something with data
  },
  function(error) {
    //do something with error
  }
);

I think you should take a look at this post I you want to better understand how promises works and behaves.

EDIT: update deprecated call to $http.

Sign up to request clarification or add additional context in comments.

10 Comments

Great so the service is good, but why is it recommended on the AngularJS site to use $q and defered if $http returns it. Might be stupid to ask but i cant get my head around it
note that success and error are deprecated in $http docs in favor of using promise then
yeah they have been deprecated. My bad, I'll update the code answer.
@user3052526 can you point to the article on the AngularJS site that recommended the use of $q with $http? It sounds like an out of date page that probably can be updated or removed....
don't think you understood the deprecation part. Also can't chain then to success
|
1

Well, in the AngularJS docs: https://docs.angularjs.org/api/ng/service/$http

Deprecation Notice The $http legacy promise methods success and error have been deprecated. Use the standard then method instead. If $httpProvider.useLegacyPromiseExtensions is set to false then these methods will throw $http/legacy error.

You don't need to use the $q promise.

As you're using GET request, you might use the shortcut method to perform GET request.: $http.get();.

So, you might try something like this:

MyService service: Only you need the $http service.

app.service("MyService", ["$http", function ($http) {
    this.getcustomers = function () {
        return $http.get("http://call/to/rest/api");
    };
}]);

The service above lets you use the service, in any controller. So, any controller can performs others action by using the same data.

registerationCtrl controller: You need the $scope, MyService and location services.

    app.controller("registerationCtrl", ["$scope", "MyService", "$location", function ($scope, MyService, location) {
        $scope.custlst = [];

        $scope.getcustomers = function () {
            MyService.getcustomers().then(function (response) {
                $scope.custlst = response.data;
            }, function (err) {
                alert(err);
            });
        };
    }]);
}]);

1 Comment

By using this way the service can be used in any controller.
1

As I mentioned in comments, the error you're seeing is due to the error variable not being declared inside the errorCallback function.

As for $q - no need to use it, although the way you implemented would still work. To make it simpler and to follow the intent of promises (i.e. that they allow async code to mirror code composition of sync code) it's better to return the original promise of $http (or of $http().then()):

this.getcustomers = function() {
  return $http({
      method: 'GET',
      url: 'http://call/to/rest/api'
    })
    // pre-process the HTTP response and return the data
    .then(function(response) {
      return response.data;
    })
    // If needed, create a custom error to hide HTTP details from caller
    // otherwise, don't include .catch - the original error will "bubble up"
    .catch(function(error) {
      return $q.reject({
        msg: "something broke"
      });
    });
};

Then, the client can be used as you intended:

MyService.getcustomers()
  .then(function(data) {
    $scope.customers = data;
  })
  .catch(function(error) {
    console.log(error.msg);
  })

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.