AngularJS service not invoking error callback on s

2020-04-02 09:51发布

问题:

So I'm using angularjs restful service $resource and I'm calling $save function. However, the error callback I pass to it is not being called. The server is sending a 418 error which I thought since it's NOT 200 would result in the error callback being invoked. But, it never does. I can't find any documentation stating what http error codes will result in the error callback being called.

Here is my code:

var modalScope = $scope.$new();
modalScope.showPassword = false;
modalScope.message = null;
modalScope.user = new User();

modalScope.submit = function(user) {
    user.$save( {}, function(data,headers) {
        // do the success case
    }, function(data,headers) {
        // do the error case                
    });
};

The modalScope.user is being passed to the submit function defined. So what's the problem why this error callback isn't being called?

回答1:

I found the following in the ngResource source code

$http({method: 'GET', url: '/someUrl'}).
    success(function(data, status, headers, config) {
        // this callback will be called asynchronously
        // when the response is available
    }).
    error(function(data, status, headers, config) {
        // called asynchronously if an error occurs
        // or server returns response with status
        // code outside of the <200, 400) range
    });

I am kind of confused about the range notation but it seems it should actually call the error method. Maybe you found a bug.



回答2:

Had the same problem and nothing here worked. Turned out I had an custom debug-interceptor that didn't explicitly return a $q.reject(response).

Apparently every custom debug-interceptor completely overwrites the default behavior.

See https://github.com/angular/angular.js/issues/2609#issuecomment-44452795 for where I found the answer.



回答3:

I had troubles with the error callback as well, but it appears that in more recent versions of AngularJS, the error callback method must now be implemented something like this:

SomeResource.query({}, angular.noop, function(response){
  $scope.status = response.status; 
});

Source + more detailed description: https://groups.google.com/d/msg/angular/3Q-Ip95GViI/at8cF5LsMHwJ

Also, in response to the comments on Flek's post, it seems that now only responses between 200 and 300 are not considered an error.



回答4:

I couldn't get Alter's answer to work, but this worked for me:

user.$save(function (user, headers) {
                    // Success
                    console.log("$save success " + JSON.stringify(user));
                }, function (error) {
                    // failure
                    console.log("$save failed " + JSON.stringify(error))
                });


回答5:

I'm copying from the ngResource documentation:

The action methods on the class object or instance object can be invoked with the following parameters:

  • HTTP GET "class" actions: Resource.action([parameters], [success], [error])
  • non-GET "class" actions: Resource.action([parameters], postData, [success], [error])
  • non-GET instance actions: instance.$action([parameters], [success], [error])

Success callback is called with (value, responseHeaders) arguments. Error callback is called with (httpResponse) argument.

$save is considered as a non-GET "class" action, so you must to use an extra postData parameter. Using the same question example, this should work:

modalScope.submit = function(user) {
    user.$save( {}, {}, function(data,headers) {
        // do the success case
    }, function(response) {
        // do the error case                
    });
};

Keep an eye on the error callback, compared with the example, is calling with just one argument, which brings all the http response.



回答6:

Actually if we follow the documentation. it works

 User.save(vm.user, function (response) {
              FlashService.Success('Registration successful', true);
              $location.path('/login');
      },
      function (response) {

          FlashService.Error(response.data);
          vm.dataLoading = false;

      });

above is snip from my code it works.