简体   繁体   中英

How can I retrieve HTTP status codes using Angular's $q promises?

I have within my code that makes an $http.post to a back end, and of course things can go wrong. If I use the below syntax within angular:

$http.post(url).success(function(data, status, headers, config))
    .error(function(data, status, headers, config));

If there is an error, I can retrieve the error code using status and handle it within the function defined in error() . However, if instead I take this approach (which is the one I am in fact using):

var deferred = $q.defer();
$http.post(url).success(deferred.resolve).error(deferred.reject);
return deferred.promise;

With the second syntax, I have all of my ajax calls within a separate ServiceJS directory, and can handle the successes or errors on a case by case basis. For instance, if the second snippet was Service.MyFunction() then in the code where I need it I would:

Service.MyFunction().then(function() {},
    function(data, status, headers, config) {});

However, if I use this code block, status , headers , config are all undefined. My question is how can I retain this syntax but still retrieve the error code?

As an added reference, the back end is a C# Web API project, which would return errors using return BadRequest(); or the like.

Try something like this:

myFunction(){
    var deferred = $q.defer();

    // you can use .then() instead of .success or .error
    $http.post(url).then(function(successResponse){
         var data = successResponse.data;
         var status = successResponse.status; 
         ...
         deferred.resolve(successResponse);
    }, function(failureResponse){
         var status = failureResponse.status; 
         var config = failureResponse.config; 
         ...            
         deferred.reject(failureResponse);
    });

    return deferred.promise;
}

well, I'd say it's a good practice and more standard to implement a http interceptor and handle the HTTP errors from there intead of handling the error one by one on each http or resource object, and your code will be located in a single location.

basically, you can segment the actions to take depending on the error status you get for example:

angular.module('app').factory('myInterceptor', ['$q',
    function($q){
        return {
            'responseError': function(rejection){
                switch(rejection.status){
                    case 0:
                        //'No connection, is the internet down?'
                        break;
                    case 422:
                        // error
                        break;
                    case 484:
                        // error
                        break;
                    default:
                        // message rejection.status, rejection.statusText
                        break;
                }
                return $q.reject(rejection);
            }
        };
    }
    ]); 

$http is already returning a promise, so why not use that one?

function myFunction() {
  return $http.post(url);
}

// ...

myFunction().success(function(data, status, headers, config) {
  // ...
});

... or ...

myFunction().then(...);

The promises returned from $http have the methods success and error in addition to the other promise methods. Read more at Angular docs for $http .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM