Simon
Simon

Reputation: 5247

intercepting $resource and $http responses angular

I have a json response:

{
  "success": false,
  "error": "Server says no.",
  "data": []
}

wrapped in $resource like this:

$resource("path-to-file.json", null, {
  query: {
    method: "GET",
    isArray: false,
    responseType: "json",
    interceptor: {
      response: function (response) {
        if (!response.data.success) {
          // stop propagation of events/promises and trigger error
        }
        // do something else with response.data
        return response;
      }
    }
  }
});

If "success": false I want to trigger the error function of $http.

I want to do this:

$scope.myVar = MyService.query(); // MyService returns $resource

in a controller. The response gets passed to $scope.myVar regardless of what I try and do.

Upvotes: 2

Views: 2044

Answers (2)

RichardTowers
RichardTowers

Reputation: 4762

It's worth remembering that:

The ngResource module provides interaction support with RESTful services 1

When they say "RESTful services" they mean that they're making some assumptions about how your endpoint is going to behave. One of these assumptions is that the success or error status is going to be encoded by the HTTP Status Code.

It sounds like you're trying to interact with a service that doesn't fit this pattern (i.e. you can have a failed request that returns 200: OK). If that's the case you'd probably better off using $http directly, since it is more general:

The $http service is a core Angular service that facilitates communication with the remote HTTP servers 2

Since $resource is really just a wrapper around $http we can confirm the behaviour fairly easily by having a look at the source (edited for clarity):

var promise = $http(httpConfig).then(function(response) {
  var data = response.data,
      promise = value.$promise;

  // snip

  value.$resolved = true;

  response.resource = value;

  return response;
}, function(response) {
  value.$resolved = true;

  (error||noop)(response);

  return $q.reject(response);
});

promise = promise.then(
    function(response) {
      var value = responseInterceptor(response);
      (success||noop)(value, response.headers);
      return value;
    },
    responseErrorInterceptor);

Remember that then() takes a success and an error callback in that order. You can see that your interceptor is going to get called on success, along with the main success callback if there is one.

It doesn't look like there's anything you can do inside your responseInterceptor that will cause the error callback to be executed.

I think your options are:

  • Modify the your server to behave in the way that $resource expects
  • Roll your own version of $resource built on top of $http that works the way you want it to as suggested in this answer.

Upvotes: 1

Chandermani
Chandermani

Reputation: 42669

Try

if (!response.data.success) {
          return $q.reject(rejection);
 }

See if this call the error callback. I got it from the documentation of $http http://docs.angularjs.org/api/ng.$http

Upvotes: 1

Related Questions