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.

3
  • 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 Commented Feb 22, 2015 at 3: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 Commented Feb 28, 2016 at 16:08
  • 1
    how to set timeout for post method $http.post('path/to/service', {data:data}); Commented Apr 13, 2018 at 12:06

4 Answers 4

106

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');
Sign up to request clarification or add additional context in comments.

6 Comments

Works like a charm and should be the accepted answer as it's 2 years later now....
Out of interest, why are you injecting $rootScope and $q? or are these used outside of the code you pasted?
Also, how do you handle this? I notice the request is cancelled, can i set a listener for this?
the best answer wich is not fully supported by actual version. Please update your answer by removing the first line talking about angular version
config.timeout = config.timeout || 10000;
|
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;
}]);

7 Comments

Are sure that code above is working? It looks like that the config.timeout is not modified when calling sendReq: 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 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 docs.angularjs.org/api/ng.$http
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: jsfiddle.net/RYDMM/4 trying to reproduce the problem, but it looks like that the timeout doesn't affect jsonp at all
Here's a gist trying to explain that it's not possible to set a default time out: gist.github.com/orjan/5013478
@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 (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: gist.github.com/adnan-i/5014277
|
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
    } 
    

1 Comment

+! for "the way to tell between an error and an abort/timeout"
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)

} ]);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.