From e7147296b1d49e1dfaa9b77f56e9e43d2cb9f670 Mon Sep 17 00:00:00 2001 From: William Bagayoko Date: Wed, 27 Jan 2016 17:25:44 -0600 Subject: [PATCH] fix($http): properly synchronize $browser outstandingRequestCount The issue is that using $http doesn't update $browser.outstandingRequestCount synchronously so that $browser.notifyWhenNoOutstandingRequests waits accordingly. Configuring this synchronization with the promise chain updates the outstandingRequestCount correctly. Closes #13782 --- src/ng/http.js | 10 ++++++++-- src/ng/httpBackend.js | 2 -- src/ngMock/angular-mocks.js | 5 +++-- test/ng/httpSpec.js | 18 ++++++++++++++++++ 4 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/ng/http.js b/src/ng/http.js index c3ba1120fde4..972fbe665b29 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 = ['$httpBackend', '$$cookieReader', '$cacheFactory', '$rootScope', '$q', '$injector', '$browser', + function($httpBackend, $$cookieReader, $cacheFactory, $rootScope, $q, $injector, $browser) { var defaultCache = $cacheFactory('$http'); @@ -968,6 +968,8 @@ function $HttpProvider() { } }); + $browser.$$incOutstandingRequestCount(); + while (chain.length) { var thenFn = chain.shift(); var rejectFn = chain.shift(); @@ -975,6 +977,10 @@ function $HttpProvider() { promise = promise.then(thenFn, rejectFn); } + promise.finally(function() { + $browser.$$completeOutstandingRequest(noop); + }); + if (useLegacyPromise) { promise.success = function(fn) { assertArgFn(fn, 'fn'); 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/src/ngMock/angular-mocks.js b/src/ngMock/angular-mocks.js index 9964b11ae559..77d7625279bd 100644 --- a/src/ngMock/angular-mocks.js +++ b/src/ngMock/angular-mocks.js @@ -37,8 +37,9 @@ angular.mock.$Browser = function() { self.pollFns = []; // TODO(vojta): remove this temporary api - self.$$completeOutstandingRequest = angular.noop; - self.$$incOutstandingRequestCount = angular.noop; + self.$$outstandingRequestCount = 0; + self.$$completeOutstandingRequest = function() { self.$$outstandingRequestCount--; }; + self.$$incOutstandingRequestCount = function() { self.$$outstandingRequestCount++; }; // register url polling fn diff --git a/test/ng/httpSpec.js b/test/ng/httpSpec.js index bc27ff5b5fe6..74ec8c488cfa 100644 --- a/test/ng/httpSpec.js +++ b/test/ng/httpSpec.js @@ -1866,6 +1866,24 @@ describe('$http', function() { expect(paramSerializer({foo: 'foo', bar: ['bar', 'baz']})).toEqual('bar=bar&bar=baz&foo=foo'); }); }); + + describe('$browser outstandingRequests', function() { + var $browser; + + beforeEach(inject(['$browser', function(browser) { + $browser = browser; + }])); + + it('should update $brower outstandingRequestCount', function() { + $httpBackend.when('GET').respond(200); + + expect($browser.$$outstandingRequestCount).toBe(0); + $http({method: 'GET', url: '/some'}); + expect($browser.$$outstandingRequestCount).toBe(1); + $httpBackend.flush(); + expect($browser.$$outstandingRequestCount).toBe(0); + }); + }); });