如何在AngularJS 1.2中获取HTTP响应状态码

26

在AngularJS 1.2rc(x)中使用ngResource,我现在如何获取状态码?

RestAPI.save({resource}, {data}, function( response, responseHeaders ) {
});

其中RestAPI是我的ngResource

响应包含了一个$promise对象和从服务器返回的资源,但不再包括状态。如果服务器将状态码注入到头部对象中,则responseHeaders()函数只有一个状态,但不是真正的返回状态码。因此,一些服务器可能会提供它,而另一些则可能不会。


看起来很相似:https://dev59.com/LWQm5IYBdhLWcg3wswpv - ekremkaraca
1
完全不相似。两个问题都涉及AngularJS和使用ngResource,但除此之外完全不同。我可以通过响应正常获取响应数据。但是我无法在1.2rc(x)中获取HTTP响应状态码,这是一个重大变化。 - Eddie Monge Jr
请参考此链接:http://stackoverflow.com/a/41179647/2851184。 - Alok Mishra
8个回答

13

$resource调用之后,你可以使用承诺回调thencatchfinally

例如,如果你想要在调用之后捕获错误,你可以像这样做:

RestAPI.save({resource}, {data}, callbackFunction).$promise.catch(function(response) {
    //this will be fired upon error
    if(response.status == 500) alert('Something baaad happend');
}).then(function() {
    //this will be fired upon success
});

response 对象将拥有 statusstatusText 属性。其中 status 是一个整数状态码,而 statusText 是文本。您还将拥有包含服务器响应的 data 属性。

编辑:根据建议,应该是 response.status


2
我从我的WebAPI返回了400,但仍然没有触发catch。"then"中没有响应。 - Mike K
不是真的,我的回复没有状态。 - Samuel Thompson

12

您必须在资源声明中添加一个拦截器。就像这样:

var resource = $resource(url, {}, {
    get: {
        method: 'GET'
        interceptor: {
            response: function(response) {      
                var result = response.resource;        
                result.$status = response.status;
                return result;
            }
        }
    }                            
});

使用方法:

resource.get(params, function(result) {
    console.log(result.$status)
});

默认情况下应该提供IMO状态代码。这个问题的解决方案可以在https://github.com/angular/angular.js/issues/8341中找到。


如果连接不成功,这将无法工作。如果出现404错误,它将不会显示。 - Mario Shtika
@MarioShtika 这是一个旧答案。你尝试过 https://dev59.com/4GMl5IYBdhLWcg3wDjSg#24791928 吗? - Ara Yeressian
据我所记,@MarioShtika,还有一个错误回调函数。在你的情况下,404错误应该在那里处理。这是很久以前的事了,我不再使用Angular编程了。 - Ara Yeressian
我相信答案是两者的结合,因为在Bardiels的回答中,它没有显示连接成功时的状态。 - Mario Shtika
@MarioShtika 是的,很可能。 - Ara Yeressian

4

对于使用新版Angular的用户,看起来我们可以通过transformResponse函数的第三个参数(从Angular 1.3版本开始)获取状态码,但它在$resource文档中没有得到适当的记录。


3

我同意responseHeaders()函数仅返回响应的头部信息,但您可以自定义它,这非常有用。

1.

为了解决您的问题,请使用以下代码:(其中$$service是我的$resource实例。)

var serve = new $$service();
serve.id = "hello_wrongPath"; // wrong path,will return 404
serve.$get()
    .then(function (data) {
        console.log("~~~hi~~~");
        console.log(data);
        return data;
    })
    .catch(function (error) {
        console.log("~~~error~~~");
        console.log(error);
        console.log(error.status); // --> 404
        console.log(error.statusText); // --> "Not Found"
        console.log(error.config.timeout); // --> 5000
        console.log(error.config.method); // --> GET
        console.log(error.config.url); // --> request url
        console.log(error.headers("content-type"));// --> "text/plain"
        return error.$promise;
    })
    .finally(function(data){
        console.log("~~~finally~~~");
        console.log(data); // --> undefined
    });

如果您想在错误响应中仅捕获status,statusText,timeout,method,headers(与responseHeaders相同),则可以使用此方法。

2.

如果您想要在成功响应中查看响应详情,可以使用以下拦截器:

ng.module("baseInterceptor", [])
    .factory("baseInterceptor", ["$q", function ($q) {
        return {
            'request': function (config) {
                console.info(config);
                //set timeout for all request
                config.timeout = 5000;
                return config;
            },
            'requestError': function (rejection) {
                console.info(rejection);
                return $q.reject(rejection);
            },
            'response': function (response) {
                console.log("~~interceptor response success~~");
                console.log(response);
                console.log(response.status);
                console.log(response.config.url);
                return response;
            },
            'responseError': function (rejection) {
                console.log("~~interceptor response error~~");
                console.log(rejection);
                console.log(rejection.status);
                return $q.reject(rejection);
            }
        };
    }]);

然后将拦截器添加到模块中:

.config(["$httpProvider", function ($httpProvider) {
    $httpProvider.interceptors.push("baseInterceptor");
}])

3
您可以像这样获取响应状态:

$http.get(url).then(function(response){
  console.log(response.status); //successful status like OK
}, function(response){
  console.log(response.status); //error status like 400-Bad Request
})


0

我认为正确的答案是Bardiel和Ara的回答的结合。

在您的资源声明中添加拦截器。像这样:

var resource = $resource(url, {}, {
    get: {
        method: 'GET'
        interceptor: {
            response: function(response) {      
                var result = response.resource;        
                result.$status = response.status;
                return result;
            }
        }
    }                            
});

使用方法如下:

RestAPI.save()
.query(function(response) {
    // This will return status code from API like 200, 201 etc
    console.log(response.$status);
})
.$promise.catch(function(response) {
    // This will return status code from server side like 404, 500 etc
    console.log(response.status);
});

0

我正在使用AngularJS v1.5.6,并且我是这样做的(在我的情况下,我将“getData”方法放在一个服务中):

function getData(url) {
    return $q(function (resolve, reject) {
        $http.get(url).then(success, error);

        function success(response) {
            resolve(response);
        }
        function error(err) {
            reject(err);
        }
    });
}

然后在控制器中(例如),像这样调用:

function sendGetRequest() {
    var promise = service.getData("someUrlGetService");
    promise.then(function(response) {
        //do something with the response data
        console.log(response.data);
    }, function(response) {
        //do something with the error
        console.log('Error status: ' + response.status);
    });
}

根据文档所述,响应对象具有以下属性:
  • data - {string | Object} - 使用转换函数转换的响应正文。
  • status - {number} - 响应的HTTP状态码。
  • headers - {function([headerName])} - 头获取器函数。
  • config - {Object} - 用于生成请求的配置对象。
  • statusText - {string} - 响应的HTTP状态文本。

请参见https://docs.angularjs.org/api/ng/service/$http

希望对您有所帮助!


-1

我曾经遇到过类似的问题。我查看了 Angular 库并添加了一些代码,以便在响应本身中返回状态。在这个文件中,找到返回 promise 的位置。

用以下代码块替换起始代码块:

var promise = $http(httpConfig).then(function(response)

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

            if (data) {
              // Need to convert action.isArray to boolean in case it is undefined
              // jshint -W018
              if ( angular.isArray(data) !== (!!action.isArray) ) {
                throw $resourceMinErr('badcfg', 'Error in resource configuration. Expected ' +
                  'response to contain an {0} but got an {1}',
                  action.isArray?'array':'object', angular.isArray(data)?'array':'object');
              }
              // jshint +W018
              if (action.isArray) {
                value.length = 0;
                forEach(data, function(item) {
                  value.push(new Resource(item));
                });
              } else {
                copy(data, value);
                value.$promise = promise;
              }
            }

            value.status = response.status;
            value.$resolved = true;

            response.resource = value;

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

            (error||noop)(response);

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

或者您可以添加这行代码

value.status = response.status;

然后在代码中像response.status那样访问状态。虽然这有点像黑客,但对我起作用。我还不得不对缩小版本进行更改。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接