angular-js: 为取消的请求设置 HTTP 状态码

angular-js: Set HTTP status code for cancelled requests

取消这样的 http 请求时:

$scope.runTest = function() {
    if (canceler) canceler.resolve();
    canceler = $q.defer();
    $http({
        method: 'GET',
        url: 'http://www.google.com/',
        timeout: canceler.promise
    })
    .success(function(data) {
        $scope.result.push({msg: "this won't be displayed on cancel"});
    })
    .error(function(data) {
        $scope.result.push({msg: "this will be displayed on cancel"});
    });
};

是否可以让取消的 HTTP 请求有一个特定的 HTTP 代码,比如 205?它会导致 http 拦截器以 http 状态 0 触发,这也用于超时或无网络连接。我希望能够区分拦截器中的两种情况

谢谢!

您需要记住 Angular $http 超时是 "client" 超时,尽管它与服务器超时具有相同的名称。 当你配置 angular $http 超时时,你是在说类似 "I'll not wait till the server timeout" 的东西。这在访问第三方时特别有用 api,因为您无法配置超时设置。

这就是 http 状态为 0 的原因。没有 http 408 响应是因为 Angular 取消请求而不是等待服务器超时。

您可以使用 $timeout 服务返回的承诺来处理客户端超时

var myTimeout = $timeout(function () {
    console.log("Cannot wait you anymore!");
}, 1000); 

$http({
    method: 'GET',
    url: 'http://www.google.com/',
    timeout: myTimeout
})
.success(function (data) {
    $scope.result.push({ msg: "this won't be displayed on cancel" });
})
.error(function (data) {
    $scope.result.push({ msg: "this will be displayed on cancel" });
});

我最终采用了以下方法:

$scope.runTest = function() {

    if (canceler) {
        // Set non-zero status for http interceptors
        // Using 499, an nginx extension to flag cancelled http requests
        // Could be something else like a boolean, using status code for convenience
        canceler.promise.status = 499;

        // Cancel the request
        canceler.resolve();
    }

    canceler = $q.defer();
    $http({
        method: 'GET',
        url: 'http://www.google.com/',
        timeout: canceler.promise
    })
    .success(function(data) {
        // On sucesss
    })
    .error(function(data) {
        // On error
    });
};

在这里,我只是在超时上设置了一些东西来将请求标记为已取消,正如@Daniel Silva 所建议的那样。然后在我的 http 拦截器上:

app.config(function($httpProvider) {

    $httpProvider.interceptors.push(function($q) {
        return {
            'responseError': function(response) {

                var statusCode = response.status;

                // Get status from timeout, if 0 and timeout present
                if (statusCode === 0 && response.config.timeout) {
                    statusCode = response.config.timeout.status;
                }

                // Ignore client request cancelled
                if (statusCode === 499) {
                    return response;
                }

                // Reject via $q, otherwise the error will pass as success
                return $q.reject(response);
            }
        };
    });
});