如何在AngularJs中设置全局http超时


76

我知道我可以每次设置超时:

$http.get('path/to/service', {timeout: 5000});

...但是我想设置一个全局超时来保持我的代码为DRY。


我认为实际上是有原因的。服务器通常具有快速和慢速的端点,我猜想角度小组不希望每个人都有最慢的超时,即使是通常应该很快的呼叫也是如此
OlivierM 2015年

1
您可以提供一个执行http请求,向其发送方法,URL和数据的服务,并在其中实现所需的任何默认配置,最好包括url的域并将其其余部分传递给它,并将它们附加到表单中完整的网址
Mohamed Selim

1
如何为发布方法设置超时$http.post('path/to/service', {data:data});
ganesh

Answers:


41

更新:$ http将不遵守默认设置,因为它在httpProvider中设置了超时(请参见注释)。可能的解决方法:https : //gist.github.com/adnan-i/5014277

原始答案:

angular.module('MyApp', [])
  .config(['$httpProvider', function($httpProvider) {
    $httpProvider.defaults.timeout = 5000;
}]);

1
确定上面的代码有效吗?似乎在调用sendReq时未修改config.timeout:github.com/angular/angular.js/blob/master/src/ng/http.js#L550与defaults.withCredentials比较上面两行,将使用默认值。
orjan

@orjan好吧,如果您要的是上面的内容,那么上面的内容将无法自动运行。该代码仅显示您自己的Angular项目的配置选项。有关更多信息,请访问docs.angularjs.org/api/ng.$http
Stewie

1
我知道它是配置示例,并且代码不是独立运行的。我也知道header和withCredentials的默认值。但是我不认为默认值适用于超时。我创建了一个jsfiddle:jsfiddle.net/RYDMM/4,试图重现该问题,但是超时似乎根本不影响jsonp
orjan

这是一个要点,试图解释说不可能设置默认超时时间:gist.github.com/orjan/5013478
orjan

2
@orjan你是绝对正确的。我依靠提供答案的文档,但这再次证明了不依赖Angular文档。在查看了源代码之后(github.com/angular/angular.js/blob/master/src/ng/http.js#L759),我可以确认您的发现-无法使用$ httpProvider设置全局超时。默认值。感谢orjan的努力。我将更新答案以提供解决方法:gist.github.com/adnan-i/5014277
Stewie

105

这可以通过出血边缘angular.js(通过git master 4ae46814ff测试)来实现。

您可以使用请求http拦截器。像这样。

 angular.module('yourapp')
  .factory('timeoutHttpIntercept', function ($rootScope, $q) {
    return {
      'request': function(config) {
        config.timeout = 10000;
        return config;
      }
    };
 });

然后在.config中注入$ httpProvider并执行以下操作:

$httpProvider.interceptors.push('timeoutHttpIntercept');

6
就像一个魅力和作品应该是公认的答案,因为它是两年后现在....
塞巴斯蒂安J.

2
出于兴趣,为什么要注入$ rootScope和$ q?还是这些代码在您粘贴的代码之外使用?
Ben Taliadoros

1
另外,您如何处理呢?我注意到请求已取消,我可以为此设置监听器吗?
Ben Taliadoros

实际版本未完全支持最佳答案。请通过删除谈论角度版本的第一行来更新您的答案
Nicolas Janel

5
config.timeout = config.timeout || 10000;
亚历山大·阿塔纳索夫

9

感谢您的帖子和更新!!

在专门针对此问题进行研究时$resource,我想详细说明一下发现的内容:

  • 此问题已记录在跟踪器中,并且在angular 1.1.5中,支持将timeout属性传递给$http请求:

https://github.com/angular/angular.js/issues/2190 http://code.angularjs.org/1.1.5/docs/api/ngResource.$resource

  • 对于早期版本的我们,特别是我使用的是angular 1.0.6,可以在第396行编辑angular-resource.js的源文件,您将找到对$http您可以在其中添加timeout属性的调用资源请求。

  • 由于未提及它,因此我必须测试Stewie的解决方案,因此当发生超时时,在错误和中止/超时之间进行区分的方法是检查“状态”参数。它将返回0超时而不是说404

    $http.get("/home", { timeout: 100 })
    .error(function(data, status, headers, config){
            console.log(status)
        }
    
  • 由于在少数情况下,我需要使用超时而不是全局设置超时,因此我将请求包装在$timeout函数中,如下所示:

    //errorHandler gets called wether it's a timeout or resource call fails
    
    var t = $timeout(errorHandler, 5000);
    myResource.$get( successHandler, errorHandler )   
    function successHandler(data){
        $timeout.cancel(t);
        //do something with data...
    }
    
    function errorHandler(data){
        //custom error handle code
    } 
    

1
+!“在错误和中止/超时之间进行区分的方法”
Bennett McElwee 2014年

1

我有相同的要求,我正在使用AngularJS 1.0.7。我提出了以下代码,因为上述解决方案对我而言似乎都不可行(从我希望超时在一个地方成为全局的意义上讲是可行的)。基本上,我米掩盖原来的$ HTTP方法和添加timeout为每个$http请求,并覆盖其它快捷方式,如getpost...这样他们就会使用新的屏蔽$http

JSFiddle用于以下代码:

/**
 * @name ngx$httpTimeoutModule
 * @description Decorates AngularJS $http service to set timeout for each
 * Ajax request.
 * 
 * Implementation notes: replace this with correct approach, once migrated to Angular 1.1.5+
 * 
 * @author Manikanta G
 */
;(function () {
    'use strict';

    var ngx$httpTimeoutModule = angular.module('ngx$httpTimeoutModule', []);

    ngx$httpTimeoutModule.provider('ngx$httpTimeout', function () {
        var self = this;
        this.config = {
            timeout: 1000 // default - 1 sec, in millis
        };

        this.$get = function () {
            return {
                config: self.config
            };
        };
    });

    /** 
     * AngularJS $http service decorator to add timeout
     */
    ngx$httpTimeoutModule.config(['$provide',  function($provide) {

        // configure $http provider to convert 'PUT', 'DELETE' methods to 'POST' requests
        $provide.decorator('$http', ['$delegate', 'ngx$httpTimeout', function($http, ngx$httpTimeout) {
            // create function which overrides $http function

            var _$http = $http;

            $http = function (config) {
                config.timeout = ngx$httpTimeout.config.timeout;
                return _$http(config);
            };
            $http.pendingRequests = _$http.pendingRequests;
            $http.defaults = _$http.defaults;

            // code copied from angular.js $HttpProvider function
            createShortMethods('get', 'delete', 'head', 'jsonp');
            createShortMethodsWithData('post', 'put');

            function createShortMethods(names) {
                angular.forEach(arguments, function(name) {
                    $http[name] = function(url, config) {
                        return $http(angular.extend(config || {}, {
                            method : name,
                            url : url
                        }));
                    };
                });
            }

            function createShortMethodsWithData(name) {
                angular.forEach(arguments, function(name) {
                    $http[name] = function(url, data, config) {
                        return $http(angular.extend(config || {}, {
                            method : name,
                            url : url,
                            data : data
                        }));
                    };
                });
            }

            return $http;
        }]);

    }]);

})();

添加对上述模块的依赖关系,并通过配置来配置超时ngx$httpTimeoutProvider,如下所示:

angular.module('App', ['ngx$httpTimeoutModule']).config([ 'ngx$httpTimeoutProvider', function(ngx$httpTimeoutProvider) {
    // config timeout for $http requests
    ngx$httpTimeoutProvider.config.timeout = 300000; // 5min (5 min * 60 sec * 1000 millis)

} ]);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.