How to set a global http timeout in AngularJs

Angularjs

Angularjs Problem Overview


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.

Angularjs Solutions


Solution 1 - Angularjs

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');

Solution 2 - Angularjs

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

Solution 3 - Angularjs

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
     } 
    

Solution 4 - Angularjs

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)

} ]);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questiondrew schmaltzView Question on Stackoverflow
Solution 1 - AngularjsGregyView Answer on Stackoverflow
Solution 2 - AngularjsStewieView Answer on Stackoverflow
Solution 3 - AngularjsLukusView Answer on Stackoverflow
Solution 4 - AngularjsmanikantaView Answer on Stackoverflow