2

So I have a service defined as follows:

angular.module('services', ['ngResource'])
    .factory('Things', function ($rootScope, $http) {
    var basePath = 'rest/things/';
    return {
        getAll: function () {
            return $http.post($rootScope.PAGES_URL + basePath + 'getAll/' + window.clientId, {});
        }
    };
});

Then, elsewhere, I'm consuming that service w/:

Things.getAll().success(function(things){
  //do something w/ things
})
.error(function(err){
  // Clearly, something went wrong w/ the request
});

What I'd like to do, is be able to "throw" the error condition if, for instance, there's a problem w/ the data at the service level. i.e.:

Data comes back as:

{
  status:500,
  message:'There was a problem w/ the data for this client'
}

And so then in the service there would be something like:

getAll: function () {
        return $http.post($rootScope.PAGES_URL + basePath + 'getAll/' + window.clientId, {})
  .throwError(function(data){
    return (data.status && data.status == 200);
  });
}

So when the throwError callback returns false, the error() promise would then be called instead of the success promise.

Does anyone have any ideas on how to accomplish this?

Thanks a bunch!

6
  • 1
    Create a deferred in your service. Actually hook into the success and error callbacks for the $http call. Inside the success, check the status property of the response; if it isn't in the 200 range, reject the deferred. Otherwise, resolve the deferred. Reject anything in the error callback. And return the deferred's promise from the service method Commented Feb 7, 2014 at 17:28
  • Ian, thanks.. can you give a code example as an answer? Also, should I maybe use an interceptor for this? docs.angularjs.org/api/ng.$http Commented Feb 7, 2014 at 17:40
  • 1
    If you're sure that all requests will follow this convention, then using an interceptor definitely makes more sense. You can create the interceptor like in the example on that page, and inside the response callback, check if the response's property, status, and if it's "bad", use $q.reject(response);, otherwise return response || $q.when(response); Commented Feb 7, 2014 at 17:44
  • Ok... but on that page it says to attach the factory for the interceptor to $provide. In my example above, can I just chain it onto my 'services' module? Also, can you add your comments above into an answer so I can credit you with it? :-) Commented Feb 7, 2014 at 18:33
  • 1
    Yeah, you should be able to chain it onto the module! And I don't think there's a benefit between the two ways that the docs provide - I like to break things up as much as possible, so I would prefer to make it a named service. I think that way, it also makes it easier to mock/test if you wanted to. Commented Feb 7, 2014 at 18:47

1 Answer 1

4

If you're sure that all requests will follow the convention where the data returned from a response includes a status code, then using an HTTP Interceptor makes sense. To do this, you can create a service and push it to the interceptor list for the $httpProvider:

.factory("myHttpInterceptor", function ($q) {
    return {
        response: function (response) {
            if (response.data.status && (response.data.status === 500)) {
                return $q.reject(response);
            }
            return response || $q.when(response);
        }
    };
});

You could replace the === 500 with something like >= 400 to handle all errors, not just a 500.

And inside your module's .config(), add this:

$httpProvider.interceptors.push("myHttpInterceptor");

References:

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

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.