feat($browser.xhr): add timeout option to abort request

Timeouted request responds internal status code -1, which should be normalized
into 0 by $xhr.
This commit is contained in:
Vojta Jina 2011-08-18 23:48:01 +02:00 committed by Igor Minar
parent 3ae3ccf3da
commit 5487bdb3d1
2 changed files with 30 additions and 3 deletions

View file

@ -95,6 +95,7 @@ function Browser(window, document, body, XHR, $log, $sniffer) {
* <li><tt>X-Requested-With</tt>: <tt>XMLHttpRequest</tt></li>
* </ul>
*
* @param {number=} timeout Timeout in ms, when the request will be aborted
* @returns {XMLHttpRequest|undefined} Raw XMLHttpRequest object or undefined when JSONP method
*
* @description
@ -102,7 +103,7 @@ function Browser(window, document, body, XHR, $log, $sniffer) {
*
* TODO(vojta): change signature of this method to (method, url, data, headers, callback)
*/
self.xhr = function(method, url, post, callback, headers) {
self.xhr = function(method, url, post, callback, headers, timeout) {
outstandingRequestCount ++;
if (lowercase(method) == 'jsonp') {
var callbackId = ("angular_" + Math.random() + '_' + (idCounter++)).replace(/\d\./, '');
@ -126,21 +127,30 @@ function Browser(window, document, body, XHR, $log, $sniffer) {
if (value) xhr.setRequestHeader(key, value);
});
var status;
xhr.send(post || '');
// IE6, IE7 bug - does sync when serving from cache
if (xhr.readyState == 4) {
setTimeout(function() {
completeOutstandingRequest(callback, fixStatus(xhr.status), xhr.responseText);
completeOutstandingRequest(callback, fixStatus(status || xhr.status), xhr.responseText);
}, 0);
} else {
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
completeOutstandingRequest(callback, fixStatus(xhr.status), xhr.responseText);
completeOutstandingRequest(callback, fixStatus(status || xhr.status),
xhr.responseText);
}
};
}
if (timeout > 0) {
setTimeout(function() {
status = -1;
xhr.abort();
}, timeout);
}
return xhr;
}
};

View file

@ -228,6 +228,23 @@ describe('browser', function() {
expect(browser.xhr('GET', '/url', null, noop)).toBe(xhr);
});
it('should abort request on timeout', function() {
var callback = jasmine.createSpy('done').andCallFake(function(status, response) {
expect(status).toBe(-1);
});
browser.xhr('GET', '/url', null, callback, {}, 2000);
xhr.abort = jasmine.createSpy('xhr.abort');
fakeWindow.setTimeout.flush();
expect(xhr.abort).toHaveBeenCalledOnce();
xhr.status = 0;
xhr.readyState = 4;
xhr.onreadystatechange();
expect(callback).toHaveBeenCalledOnce();
});
it('should be async even if xhr.send() is sync', function() {
// IE6, IE7 is sync when serving from cache
var xhr;