Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 904cc39

Browse files
committed
fix($http): correct behavior
1 parent e5c6174 commit 904cc39

File tree

5 files changed

+42
-10
lines changed

5 files changed

+42
-10
lines changed

src/ng/http.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -845,6 +845,8 @@ function $HttpProvider() {
845845
* See {@link $http#caching $http Caching} for more information.
846846
* - **timeout** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise}
847847
* that should abort the request when resolved.
848+
* A numerical timeout or `$timeout` will set `xhrStatus` "timeout", and a resolved promise
849+
* will set it to "abort", following standard XMLHttpRequest behavior.
848850
* - **withCredentials** - `{boolean}` - whether to set the `withCredentials` flag on the
849851
* XHR object. See [requests with credentials](https://developer.mozilla.org/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials)
850852
* for more information.

src/ng/httpBackend.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,15 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
120120
};
121121

122122
xhr.onerror = requestError;
123-
xhr.onabort = requestAborted;
124123
xhr.ontimeout = requestTimeout;
125124

125+
// The timeout behavior follows standard XMLHttpRequest logic.
126+
// xhr.timeout = ontimeout (numerical timeout or $timeout)
127+
// xhr.abort() = onabort (resolving a promise)
128+
xhr.onabort = timeout > 0 || (timeout && timeout.$$timeoutId >= 0) ? requestTimeout : requestAborted;
129+
126130
forEach(eventHandlers, function(value, key) {
127-
xhr.addEventListener(key, value);
131+
xhr.addEventListener(key, value);
128132
});
129133

130134
forEach(uploadEventHandlers, function(value, key) {

src/ngMock/angular-mocks.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1378,9 +1378,13 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
13781378
function wrapResponse(wrapped) {
13791379
if (!$browser && timeout) {
13801380
if (timeout.then) {
1381-
timeout.then(handleTimeout);
1381+
timeout.then(function() {
1382+
handlePrematureEnd(timeout.$$timeoutId >= 0 ? 'timeout' : 'abort');
1383+
});
13821384
} else {
1383-
$timeout(handleTimeout, timeout);
1385+
$timeout(function() {
1386+
handlePrematureEnd('timeout');
1387+
}, timeout);
13841388
}
13851389
}
13861390

@@ -1394,11 +1398,11 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
13941398
copy(response[3] || ''), copy(response[4]));
13951399
}
13961400

1397-
function handleTimeout() {
1401+
function handlePrematureEnd(reason) {
13981402
for (var i = 0, ii = responses.length; i < ii; i++) {
13991403
if (responses[i] === handleResponse) {
14001404
responses.splice(i, 1);
1401-
callback(-1, undefined, '', undefined, 'timeout');
1405+
callback(-1, undefined, '', undefined, reason);
14021406
break;
14031407
}
14041408
}

test/ng/httpSpec.js

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1907,7 +1907,7 @@ describe('$http', function() {
19071907
function(response) {
19081908
expect(response.data).toBeUndefined();
19091909
expect(response.status).toBe(-1);
1910-
expect(response.xhrStatus).toBe('timeout');
1910+
expect(response.xhrStatus).toBe('abort');
19111911
expect(response.headers()).toEqual(Object.create(null));
19121912
expect(response.config.url).toBe('/some');
19131913
callback();
@@ -1923,17 +1923,39 @@ describe('$http', function() {
19231923
}));
19241924

19251925

1926+
it('should timeout request when numerical timeout is exceeded', inject(function($timeout) {
1927+
var onFulfilled = jasmine.createSpy('onFulfilled');
1928+
var onRejected = jasmine.createSpy('onRejected').and.callFake(function(response) {
1929+
expect(response.xhrStatus).toBe('timeout');
1930+
callback();
1931+
});
1932+
1933+
$httpBackend.expect('GET', '/some').respond(200);
1934+
1935+
$http({method: 'GET', url: '/some', timeout: 10}).then(onFulfilled, onRejected);
1936+
1937+
$timeout.flush(100);
1938+
1939+
expect(onFulfilled).not.toHaveBeenCalled();
1940+
expect(callback).toHaveBeenCalled();
1941+
}));
1942+
1943+
19261944
it('should reject promise when timeout promise resolves', inject(function($timeout) {
19271945
var onFulfilled = jasmine.createSpy('onFulfilled');
1928-
var onRejected = jasmine.createSpy('onRejected');
1946+
var onRejected = jasmine.createSpy('onRejected').and.callFake(function(response) {
1947+
expect(response.xhrStatus).toBe('timeout');
1948+
callback();
1949+
});
1950+
19291951
$httpBackend.expect('GET', '/some').respond(200);
19301952

19311953
$http({method: 'GET', url: '/some', timeout: $timeout(noop, 10)}).then(onFulfilled, onRejected);
19321954

19331955
$timeout.flush(100);
19341956

19351957
expect(onFulfilled).not.toHaveBeenCalled();
1936-
expect(onRejected).toHaveBeenCalledOnce();
1958+
expect(callback).toHaveBeenCalled();
19371959
}));
19381960
});
19391961

test/ngMock/angular-mocksSpec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1669,7 +1669,7 @@ describe('ngMock', function() {
16691669

16701670
canceler(); // simulate promise resolution
16711671

1672-
expect(callback).toHaveBeenCalledWith(-1, undefined, '', undefined, 'timeout');
1672+
expect(callback).toHaveBeenCalledWith(-1, undefined, '', undefined, 'abort');
16731673
hb.verifyNoOutstandingExpectation();
16741674
hb.verifyNoOutstandingRequest();
16751675
});

0 commit comments

Comments
 (0)