Skip to content

Commit

Permalink
Added new feature to abort a pending request. Fixes issue angular#1159.
Browse files Browse the repository at this point in the history
  • Loading branch information
David Bennett committed Nov 29, 2012
1 parent a03e370 commit fb16ce9
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 6 deletions.
15 changes: 13 additions & 2 deletions src/ng/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,7 @@ function $HttpProvider() {
reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},
defHeaders.common, defHeaders[lowercase(config.method)], config.headers),
reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),
promise;
promise, abortFn;

// strip content-type if data is undefined
if (isUndefined(config.data)) {
Expand All @@ -489,13 +489,17 @@ function $HttpProvider() {
// send request
promise = sendReq(config, reqData, reqHeaders);

// save a reference to the abort function
abortFn = promise.abort;

// transform future response
promise = promise.then(transformResponse, transformResponse);
promise.abort = abortFn;

// apply interceptors
forEach(responseInterceptors, function(interceptor) {
promise = interceptor(promise);
promise.abort = abortFn;
});

promise.success = function(fn) {
Expand Down Expand Up @@ -661,13 +665,20 @@ function $HttpProvider() {
function sendReq(config, reqData, reqHeaders) {
var deferred = $q.defer(),
promise = deferred.promise,
abortFn,
cache,
cachedResp,
url = buildUrl(config.url, config.params);

$http.pendingRequests.push(config);
promise.then(removePendingReq, removePendingReq);

promise.abort = function() {
if (isFunction(abortFn)) {
abortFn();
}
}


if (config.cache && config.method == 'GET') {
cache = isObject(config.cache) ? config.cache : defaultCache;
Expand Down Expand Up @@ -696,7 +707,7 @@ function $HttpProvider() {

// if we won't have the response in cache, send the request to the backend
if (!cachedResp) {
$httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,
abortFn = $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,
config.withCredentials);
}

Expand Down
12 changes: 8 additions & 4 deletions src/ng/httpBackend.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,15 @@ function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument,
xhr.send(post || '');

if (timeout > 0) {
$browserDefer(function() {
status = -1;
xhr.abort();
}, timeout);
$browserDefer(abortRequest, timeout);
}

return abortRequest;

function abortRequest() {
status = -1;
xhr.abort();
};
}


Expand Down
21 changes: 21 additions & 0 deletions test/ng/httpBackendSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,27 @@ describe('$httpBackend', function() {
});


it('should return an abort function', function() {
callback.andCallFake(function(status, response) {
expect(status).toBe(-1);
});

var abort = $backend('GET', '/url', null, callback);
xhr = MockXhr.$$lastInstance;
spyOn(xhr, 'abort');

expect(typeof abort).toBe('function');

abort();
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);
Expand Down
32 changes: 32 additions & 0 deletions test/ng/httpSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -978,4 +978,36 @@ describe('$http', function() {

$httpBackend.verifyNoOutstandingExpectation = noop;
});


it('should abort pending requests', function() {
var $httpBackend = jasmine.createSpy('$httpBackend');
var abortFn = jasmine.createSpy('abortFn');

$httpBackend.andCallFake(function(m, u, d, callback) {
abortFn.andCallFake(function() {
callback(-1, 'bad error', '');
});
return abortFn;
});

module(function($provide) {
$provide.value('$httpBackend', $httpBackend, '');
});

inject(function($http) {
$http({method: 'GET', url: 'some.html'}).error(function(data, status, headers, config) {
expect(data).toBe('bad error');
expect(status).toBe(0);
expect(headers()).toEqual({});
expect(config.url).toBe('some.html');
callback();
}).abort();
expect($httpBackend).toHaveBeenCalledOnce();
expect(abortFn).toHaveBeenCalledOnce();
expect(callback).toHaveBeenCalledOnce();
});

$httpBackend.verifyNoOutstandingExpectation = noop;
});
});

0 comments on commit fb16ce9

Please sign in to comment.