diff --git a/src/ng/http.js b/src/ng/http.js
index 9f0a821f3e0f..524044f6d50e 100644
--- a/src/ng/http.js
+++ b/src/ng/http.js
@@ -375,8 +375,8 @@ function $HttpProvider() {
**/
var interceptorFactories = this.interceptors = [];
- this.$get = ['$httpBackend', '$$cookieReader', '$cacheFactory', '$rootScope', '$q', '$injector',
- function($httpBackend, $$cookieReader, $cacheFactory, $rootScope, $q, $injector) {
+ this.$get = ['$browser', '$httpBackend', '$$cookieReader', '$cacheFactory', '$rootScope', '$q', '$injector',
+ function($browser, $httpBackend, $$cookieReader, $cacheFactory, $rootScope, $q, $injector) {
var defaultCache = $cacheFactory('$http');
@@ -956,7 +956,7 @@ function $HttpProvider() {
};
var chain = [serverRequest, undefined];
- var promise = $q.when(config);
+ var promise = initiateOutstandingRequest(config);
// apply interceptors
forEach(reversedInterceptors, function(interceptor) {
@@ -975,6 +975,8 @@ function $HttpProvider() {
promise = promise.then(thenFn, rejectFn);
}
+ promise.finally(completeOutstandingRequest);
+
if (useLegacyPromise) {
promise.success = function(fn) {
assertArgFn(fn, 'fn');
@@ -1000,6 +1002,15 @@ function $HttpProvider() {
return promise;
+ function initiateOutstandingRequest(config) {
+ $browser.$$incOutstandingRequestCount();
+ return $q.when(config);
+ }
+
+ function completeOutstandingRequest() {
+ $browser.$$completeOutstandingRequest(noop);
+ }
+
function transformResponse(response) {
// make a copy since the response must be cacheable
var resp = extend({}, response);
diff --git a/src/ng/httpBackend.js b/src/ng/httpBackend.js
index 0b16b34a7748..f857cefb9c23 100644
--- a/src/ng/httpBackend.js
+++ b/src/ng/httpBackend.js
@@ -55,7 +55,6 @@ function $HttpBackendProvider() {
function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) {
// TODO(vojta): fix the signature
return function(method, url, post, callback, headers, timeout, withCredentials, responseType) {
- $browser.$$incOutstandingRequestCount();
url = url || $browser.url();
if (lowercase(method) == 'jsonp') {
@@ -158,7 +157,6 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
jsonpDone = xhr = null;
callback(status, response, headersString, statusText);
- $browser.$$completeOutstandingRequest(noop);
}
};
diff --git a/test/e2e/fixtures/http/index.html b/test/e2e/fixtures/http/index.html
new file mode 100644
index 000000000000..57cd3ca795cd
--- /dev/null
+++ b/test/e2e/fixtures/http/index.html
@@ -0,0 +1,8 @@
+
+
+
+
+
+
diff --git a/test/e2e/fixtures/http/script.js b/test/e2e/fixtures/http/script.js
new file mode 100644
index 000000000000..db636b84734d
--- /dev/null
+++ b/test/e2e/fixtures/http/script.js
@@ -0,0 +1,29 @@
+angular.module('test', [])
+ .controller('TestCtrl', function($scope, $http, $cacheFactory, $timeout) {
+ var cache = $cacheFactory('sites');
+ var siteUrl = "http://some.site";
+ cache.put(siteUrl, "Something");
+ $http.get(siteUrl, {cache: cache}).then(function(data) {
+ $scope.text = "Hello, world!";
+ });
+ })
+ .config(function($httpProvider) {
+ $httpProvider.interceptors.push(function($q, $window) {
+ return {
+ 'request': function(config) {
+ return $q(function(resolve,reject) {
+ $window.setTimeout(function() {
+ resolve(config);
+ }, 50);
+ });
+ },
+ 'response': function(response) {
+ return $q(function(resolve,reject) {
+ $window.setTimeout(function() {
+ resolve(response);
+ }, 50);
+ });
+ }
+ };
+ });
+ });
diff --git a/test/e2e/tests/httpSpec.js b/test/e2e/tests/httpSpec.js
new file mode 100644
index 000000000000..66a0990c179f
--- /dev/null
+++ b/test/e2e/tests/httpSpec.js
@@ -0,0 +1,11 @@
+
+describe('$http', function() {
+ beforeEach(function() {
+ loadFixture("http").andWaitForAngular();
+ });
+
+ it('should have the interpolated text', function() {
+ expect(element(by.binding('text')).getText())
+ .toBe('Hello, world!');
+ });
+});
diff --git a/test/ng/httpSpec.js b/test/ng/httpSpec.js
index bc27ff5b5fe6..eb2b4af4ed2c 100644
--- a/test/ng/httpSpec.js
+++ b/test/ng/httpSpec.js
@@ -1866,6 +1866,37 @@ describe('$http', function() {
expect(paramSerializer({foo: 'foo', bar: ['bar', 'baz']})).toEqual('bar=bar&bar=baz&foo=foo');
});
});
+
+ describe('$browser\'s outstandingRequestCount', function() {
+ var incOutstandingRequestCountSpy, completeOutstandingRequestSpy;
+
+ beforeEach(inject(function($browser) {
+ incOutstandingRequestCountSpy
+ = spyOn($browser, '$$incOutstandingRequestCount').andCallThrough();
+ completeOutstandingRequestSpy
+ = spyOn($browser, '$$completeOutstandingRequest').andCallThrough();
+ }));
+
+ it('should update $browser outstandingRequestCount on success', function() {
+ $httpBackend.when('GET').respond(200);
+
+ expect(incOutstandingRequestCountSpy).not.toHaveBeenCalled();
+ $http.get('');
+ expect(incOutstandingRequestCountSpy).toHaveBeenCalledOnce();
+ $httpBackend.flush();
+ expect(completeOutstandingRequestSpy).toHaveBeenCalledOnce();
+ });
+
+ it('should update $browser outstandingRequestCount on error', function() {
+ $httpBackend.when('GET').respond(500);
+
+ expect(incOutstandingRequestCountSpy).not.toHaveBeenCalled();
+ $http.get('');
+ expect(incOutstandingRequestCountSpy).toHaveBeenCalledOnce();
+ $httpBackend.flush();
+ expect(completeOutstandingRequestSpy).toHaveBeenCalledOnce();
+ });
+ });
});