diff --git a/src/ng/httpBackend.js b/src/ng/httpBackend.js index dcb15f77a7f6..5496589be50f 100644 --- a/src/ng/httpBackend.js +++ b/src/ng/httpBackend.js @@ -34,6 +34,8 @@ function $HttpBackendProvider() { } function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) { + var ABORTED = -1; + // TODO(vojta): fix the signature return function(method, url, post, callback, headers, timeout, withCredentials, responseType) { var status; @@ -69,13 +71,19 @@ function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, // always async xhr.onreadystatechange = function() { if (xhr.readyState == 4) { - var responseHeaders = xhr.getAllResponseHeaders(); + var responseHeaders = null, + response = null; + + if(status !== ABORTED) { + responseHeaders = xhr.getAllResponseHeaders(); + response = xhr.responseType ? xhr.response : xhr.responseText; + } // responseText is the old-school way of retrieving response (supported by IE8 & 9) // response/responseType properties were introduced in XHR Level2 spec (supported by IE10) completeRequest(callback, status || xhr.status, - (xhr.responseType ? xhr.response : xhr.responseText), + response, responseHeaders); } }; @@ -99,7 +107,7 @@ function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, function timeoutRequest() { - status = -1; + status = ABORTED; jsonpDone && jsonpDone(); xhr && xhr.abort(); } diff --git a/test/ng/httpBackendSpec.js b/test/ng/httpBackendSpec.js index b262d8a27214..cc73ea8e2d13 100644 --- a/test/ng/httpBackendSpec.js +++ b/test/ng/httpBackendSpec.js @@ -118,6 +118,25 @@ describe('$httpBackend', function() { }); }); + it('should not try to read response data when request is aborted', function() { + callback.andCallFake(function(status, response, headers) { + expect(status).toBe(-1); + expect(response).toBe(null); + expect(headers).toBe(null); + }); + $backend('GET', '/url', null, callback, {}, 2000); + xhr = MockXhr.$$lastInstance; + spyOn(xhr, 'abort'); + + fakeTimeout.flush(); + expect(xhr.abort).toHaveBeenCalledOnce(); + + xhr.status = 0; + xhr.readyState = 4; + xhr.onreadystatechange(); + expect(callback).toHaveBeenCalledOnce(); + }); + it('should abort request on timeout', function() { callback.andCallFake(function(status, response) { expect(status).toBe(-1);