77

I know I can set a timeout each and every time:

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

... but I want to set a global timeout to keep my code DRY.

drew schmaltz
  • 1,584
  • 4
  • 19
  • 29
  • I think there is actually a reason for that. The server typically has fast and slow endpoints, and i guess the angular team didn't want everybody to have the slowest possible timeout even for calls that should normally be fast – OlivierM Feb 22 '15 at 03:18
  • 1
    you can make a service that does http requests, send it method, url and data and inside it implement whatever default configurations you want it's also better to include the domain of the url and pass it just the rest of it, and it appends them forming the complete url – Mohamed Ali Feb 28 '16 at 16:08
  • 1
    how to set timeout for post method `$http.post('path/to/service', {data:data});` – ganesh Apr 13 '18 at 12:06

4 Answers4

107

This is possible with bleeding-edge angular.js (tested with git master 4ae46814ff).

You can use request http interceptor. Like this.

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

And then in .config inject $httpProvider and do this:

$httpProvider.interceptors.push('timeoutHttpIntercept');
Gregy
  • 1,343
  • 3
  • 9
  • 8
41

UPDATED: $http will not respect default setting for timeout set it in httpProvider (see the comments). Possible workaround: https://gist.github.com/adnan-i/5014277

Original answer:

angular.module('MyApp', [])
  .config(['$httpProvider', function($httpProvider) {
    $httpProvider.defaults.timeout = 5000;
}]);
Stewie
  • 60,366
  • 20
  • 146
  • 113
  • 1
    Are sure that code above is working? It looks like that the config.timeout is not modified when calling sendReq: https://github.com/angular/angular.js/blob/master/src/ng/http.js#L550 Compare with defaults.withCredentials a couple of lines above, that will fallback on the default. – orjan Feb 22 '13 at 12:42
  • @orjan Well, the above won't work on itself, if that's what you're asking. The code just shows a configuration option for your own Angular project. For further info you may take a look at 'Setting HTTP Headers' and 'Parameters' sections at http://docs.angularjs.org/api/ng.$http – Stewie Feb 22 '13 at 12:47
  • 1
    I'm aware about it's configuration example and that the code is not running on its own. I'm also aware about the defaults for header and withCredentials. But I don't think the defaults is working for the timeout. I have created a jsfiddle: http://jsfiddle.net/RYDMM/4/ trying to reproduce the problem, but it looks like that the timeout doesn't affect jsonp at all – orjan Feb 22 '13 at 13:18
  • Here's a gist trying to explain that it's not possible to set a default time out: https://gist.github.com/orjan/5013478 – orjan Feb 22 '13 at 13:47
  • 2
    @orjan You are absolutely right. I relied on documentation wile providing the answer but once again this proves that Angular docs are not to be relied upon. After taking a look at the source (https://github.com/angular/angular.js/blob/master/src/ng/http.js#L759) I can confirm your findings - it's not possible to set a global timeout using $httpProvider.defaults. Thank you orjan, for your diligence. I'll update my answer to offer my workaround: https://gist.github.com/adnan-i/5014277 – Stewie Feb 22 '13 at 15:46
  • Thanks everyone for the hard work. Would it be reasonable to say the best course of action here is to simply define the timeout in every call and wait for AngularJS to release a version with timeout as a config setting? – drew schmaltz Feb 22 '13 at 21:04
  • Consider using http://stackoverflow.com/a/15702500/25332 if your Angular stack allows it – Sebastian J. Mar 02 '15 at 15:42
9

Thanks for the post and update!!

In researching this issue specifically for $resource, I thought I'd elaborate on what I've found:

  • This issue was logged in the tracker and in angular 1.1.5, there is support for passing the timeout property through to the $http request:

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

  • For those of us on earlier versions, specifically I am using angular 1.0.6, it is possible to edit the source file for angular-resource.js on line 396 you will find the call to $http where you can add the timeout property yourself for all resource requests.

  • Since it wasn't mentioned and I had to test Stewie's solution, when a timeout does occur, the way to tell between an error and an abort/timeout is checking the 'status' argument. It will return 0 for timeouts instead of say 404:

    $http.get("/home", { timeout: 100 })
    .error(function(data, status, headers, config){
            console.log(status)
        }
    
  • Since there are only a few cases where I need to use a timeout as opposed to setting it globally, I am wrapping the requests in a $timeout function, like so:

    //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
    } 
    
deem
  • 1,252
  • 1
  • 19
  • 38
Lukus
  • 1,038
  • 1
  • 11
  • 11
1

I've the same requirement and I m using AngularJS 1.0.7. I've come up with the below code as none of the above solutions seems feasible for me (feasible in the sense I want timeout to be global at one place). Basically, I m masking the original $http methods and adding timeout for each $http request and overriding other shortcut methods, like get, post, ... so that they'll use the new masked $http.

JSFiddle for below code:

/**
 * @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;
        }]);

    }]);

})();

Add dependency on the above module, and configure the timeout by configuring ngx$httpTimeoutProvider, like below:

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)

} ]);
manikanta
  • 8,100
  • 5
  • 59
  • 66