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

feat($http) XHR progress events #3606

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion src/ng/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -730,6 +730,13 @@ function $HttpProvider() {
return promise;
};

promise.notify = function(fn) {
promise.then(null, null, function(event) {
fn(event, config);
});
return promise;
};

return promise;

function transformResponse(response) {
Expand Down Expand Up @@ -959,7 +966,7 @@ function $HttpProvider() {

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

Expand All @@ -986,6 +993,13 @@ function $HttpProvider() {
if (!$rootScope.$$phase) $rootScope.$apply();
}

/**
* Progress callback for $httpBackend
*/
function progress(event) {
deferred.notify(event);
}


/**
* Resolves the raw $http promise.
Expand Down
10 changes: 9 additions & 1 deletion src/ng/httpBackend.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
var ABORTED = -1;

// TODO(vojta): fix the signature
return function(method, url, post, callback, headers, timeout, withCredentials, responseType) {
return function(method, url, post, progressback, callback, headers, timeout, withCredentials, responseType) {
var status;
$browser.$$incOutstandingRequestCount();
url = url || $browser.url();
Expand Down Expand Up @@ -97,6 +97,14 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
}
};

if (xhr.onprogress !== undefined) {
xhr.onprogress = progressback;

if (xhr.upload !== undefined) {
xhr.upload.onprogress = progressback;
}
}

if (withCredentials) {
xhr.withCredentials = true;
}
Expand Down
6 changes: 4 additions & 2 deletions src/ngMock/angular-mocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -1131,7 +1131,8 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
}

// TODO(vojta): change params to: method, url, data, headers, callback
function $httpBackend(method, url, data, callback, headers, timeout, withCredentials) {
function $httpBackend(method, url, data, progressback, callback, headers, timeout,
withCredentials) {
var xhr = new MockXhr(),
expectation = expectations[0],
wasExpected = false;
Expand Down Expand Up @@ -1190,7 +1191,7 @@ function createHttpBackendMock($rootScope, $delegate, $browser) {
// if $browser specified, we do auto flush all requests
($browser ? $browser.defer : responsesPush)(wrapResponse(definition));
} else if (definition.passThrough) {
$delegate(method, url, data, callback, headers, timeout, withCredentials);
$delegate(method, url, data, progressback, callback, headers, timeout, withCredentials);
} else throw new Error('No response defined !');
return;
}
Expand Down Expand Up @@ -1654,6 +1655,7 @@ function MockXhr() {
};

this.abort = angular.noop;
this.onprogress = angular.noop;
}


Expand Down
64 changes: 35 additions & 29 deletions test/ng/httpBackendSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ describe('$httpBackend', function() {


it('should do basics - open async xhr and send data', function() {
$backend('GET', '/some-url', 'some-data', noop);
$backend('GET', '/some-url', 'some-data', noop, noop);
xhr = MockXhr.$$lastInstance;

expect(xhr.$$method).toBe('GET');
Expand All @@ -80,7 +80,7 @@ describe('$httpBackend', function() {
expect(status).toBe(204);
});

$backend('GET', 'URL', null, callback);
$backend('GET', 'URL', null, noop, callback);
xhr = MockXhr.$$lastInstance;

xhr.status = 1223;
Expand All @@ -94,7 +94,7 @@ describe('$httpBackend', function() {
// with readyState === 4 on mobile webkit caused by
// xhrs that are resolved while the app is in the background (see #5426).
it('should not process onreadystatechange callback with readyState == 4 more than once', function() {
$backend('GET', 'URL', null, callback);
$backend('GET', 'URL', null, noop, callback);
xhr = MockXhr.$$lastInstance;

xhr.status = 200;
Expand All @@ -106,7 +106,7 @@ describe('$httpBackend', function() {
});

it('should set only the requested headers', function() {
$backend('POST', 'URL', null, noop, {'X-header1': 'value1', 'X-header2': 'value2'});
$backend('POST', 'URL', null, noop, noop, {'X-header1': 'value1', 'X-header2': 'value2'});
xhr = MockXhr.$$lastInstance;

expect(xhr.$$reqHeaders).toEqual({
Expand All @@ -116,7 +116,7 @@ describe('$httpBackend', function() {
});

it('should set requested headers even if they have falsy values', function() {
$backend('POST', 'URL', null, noop, {
$backend('POST', 'URL', null, noop, noop, {
'X-header1': 0,
'X-header2': '',
'X-header3': false,
Expand All @@ -138,7 +138,7 @@ describe('$httpBackend', function() {
expect(response).toBe(null);
expect(headers).toBe(null);
});
$backend('GET', '/url', null, callback, {}, 2000);
$backend('GET', '/url', null, noop, callback, {}, 2000);
xhr = MockXhr.$$lastInstance;
spyOn(xhr, 'abort');

Expand All @@ -156,7 +156,7 @@ describe('$httpBackend', function() {
expect(status).toBe(-1);
});

$backend('GET', '/url', null, callback, {}, 2000);
$backend('GET', '/url', null, noop, callback, {}, 2000);
xhr = MockXhr.$$lastInstance;
spyOn(xhr, 'abort');

Expand All @@ -177,7 +177,7 @@ describe('$httpBackend', function() {
expect(status).toBe(-1);
});

$backend('GET', '/url', null, callback, {}, $timeout(noop, 2000));
$backend('GET', '/url', null, noop, callback, {}, $timeout(noop, 2000));
xhr = MockXhr.$$lastInstance;
spyOn(xhr, 'abort');

Expand All @@ -196,7 +196,7 @@ describe('$httpBackend', function() {
expect(status).toBe(200);
});

$backend('GET', '/url', null, callback, {}, $timeout(noop, 2000));
$backend('GET', '/url', null, noop, callback, {}, $timeout(noop, 2000));
xhr = MockXhr.$$lastInstance;
spyOn(xhr, 'abort');

Expand All @@ -215,7 +215,7 @@ describe('$httpBackend', function() {
expect(status).toBe(200);
});

$backend('GET', '/url', null, callback, {}, 2000);
$backend('GET', '/url', null, noop, callback, {}, 2000);
xhr = MockXhr.$$lastInstance;
spyOn(xhr, 'abort');

Expand Down Expand Up @@ -253,21 +253,20 @@ describe('$httpBackend', function() {
});

$backend = createHttpBackend($browser, function() { return new SyncXhr() });
$backend('GET', '/url', null, callback);
$backend('GET', '/url', null, noop, callback);
expect(callback).toHaveBeenCalledOnce();
});


it('should set withCredentials', function() {
$backend('GET', '/some.url', null, callback, {}, null, true);
$backend('GET', '/some.url', null, noop, callback, {}, null, true);
expect(MockXhr.$$lastInstance.withCredentials).toBe(true);
});


describe('responseType', function() {

it('should set responseType and return xhr.response', function() {
$backend('GET', '/whatever', null, callback, {}, null, null, 'blob');
$backend('GET', '/whatever', null, noop, callback, {}, null, null, 'blob');

var xhrInstance = MockXhr.$$lastInstance;
expect(xhrInstance.responseType).toBe('blob');
Expand All @@ -287,7 +286,7 @@ describe('$httpBackend', function() {
it('should read responseText if response was not defined', function() {
// old browsers like IE8, don't support responseType, so they always respond with responseText

$backend('GET', '/whatever', null, callback, {}, null, null, 'blob');
$backend('GET', '/whatever', null, noop, callback, {}, null, null, 'blob');

var xhrInstance = MockXhr.$$lastInstance;
var responseText = '{"some": "object"}';
Expand All @@ -305,6 +304,13 @@ describe('$httpBackend', function() {
});
});

it('should call progress callback', function() {
$backend('POST', '/whatever', null, callback, noop, {}, null, null, 'blob');

MockXhr.$$lastInstance.onprogress();

expect(callback).toHaveBeenCalledOnce();
});

describe('JSONP', function() {

Expand All @@ -317,7 +323,7 @@ describe('$httpBackend', function() {
expect(response).toBe('some-data');
});

$backend('JSONP', 'http://example.org/path?cb=JSON_CALLBACK', null, callback);
$backend('JSONP', 'http://example.org/path?cb=JSON_CALLBACK', null, noop, callback);
expect(fakeDocument.$$scripts.length).toBe(1);

var script = fakeDocument.$$scripts.shift(),
Expand All @@ -338,7 +344,7 @@ describe('$httpBackend', function() {


it('should clean up the callback and remove the script', function() {
$backend('JSONP', 'http://example.org/path?cb=JSON_CALLBACK', null, callback);
$backend('JSONP', 'http://example.org/path?cb=JSON_CALLBACK', null, noop, callback);
expect(fakeDocument.$$scripts.length).toBe(1);


Expand All @@ -362,7 +368,7 @@ describe('$httpBackend', function() {
if(msie<=8) {

it('should attach onreadystatechange handler to the script object', function() {
$backend('JSONP', 'http://example.org/path?cb=JSON_CALLBACK', null, noop);
$backend('JSONP', 'http://example.org/path?cb=JSON_CALLBACK', null, noop, noop);

expect(fakeDocument.$$scripts[0].onreadystatechange).toEqual(jasmine.any(Function));

Expand All @@ -377,7 +383,7 @@ describe('$httpBackend', function() {
} else {

it('should attach onload and onerror handlers to the script object', function() {
$backend('JSONP', 'http://example.org/path?cb=JSON_CALLBACK', null, noop);
$backend('JSONP', 'http://example.org/path?cb=JSON_CALLBACK', null, noop, noop);

expect(fakeDocument.$$scripts[0].onload).toEqual(jasmine.any(Function));
expect(fakeDocument.$$scripts[0].onerror).toEqual(jasmine.any(Function));
Expand All @@ -397,7 +403,7 @@ describe('$httpBackend', function() {
expect(response).toBeUndefined();
});

$backend('JSONP', 'http://example.org/path?cb=JSON_CALLBACK', null, callback);
$backend('JSONP', 'http://example.org/path?cb=JSON_CALLBACK', null, noop, callback);
expect(fakeDocument.$$scripts.length).toBe(1);

var script = fakeDocument.$$scripts.shift();
Expand All @@ -412,11 +418,11 @@ describe('$httpBackend', function() {


it('should set url to current location if not specified or empty string', function() {
$backend('JSONP', undefined, null, callback);
$backend('JSONP', undefined, null, noop, callback);
expect(fakeDocument.$$scripts[0].src).toBe($browser.url());
fakeDocument.$$scripts.shift();

$backend('JSONP', '', null, callback);
$backend('JSONP', '', null, noop, callback);
expect(fakeDocument.$$scripts[0].src).toBe($browser.url());
});

Expand All @@ -426,7 +432,7 @@ describe('$httpBackend', function() {
expect(status).toBe(-1);
});

$backend('JSONP', 'http://example.org/path?cb=JSON_CALLBACK', null, callback, null, 2000);
$backend('JSONP', 'http://example.org/path?cb=JSON_CALLBACK', null, noop, callback, null, 2000);
expect(fakeDocument.$$scripts.length).toBe(1);
expect(fakeTimeout.delays[0]).toBe(2000);

Expand Down Expand Up @@ -459,7 +465,7 @@ describe('$httpBackend', function() {
it('should convert 0 to 200 if content', function() {
$backend = createHttpBackend($browser, createMockXhr);

$backend('GET', 'someProtocol:///whatever/index.html', null, callback);
$backend('GET', 'someProtocol:///whatever/index.html', null, noop, callback);
respond(0, 'SOME CONTENT');

expect(callback).toHaveBeenCalled();
Expand All @@ -470,7 +476,7 @@ describe('$httpBackend', function() {
it('should convert 0 to 404 if no content', function() {
$backend = createHttpBackend($browser, createMockXhr);

$backend('GET', 'someProtocol:///whatever/index.html', null, callback);
$backend('GET', 'someProtocol:///whatever/index.html', null, noop, callback);
respond(0, '');

expect(callback).toHaveBeenCalled();
Expand Down Expand Up @@ -498,7 +504,7 @@ describe('$httpBackend', function() {

$backend = createHttpBackend($browser, createMockXhr);

$backend('GET', '/whatever/index.html', null, callback);
$backend('GET', '/whatever/index.html', null, noop, callback);
respond(0, '');

expect(callback).toHaveBeenCalled();
Expand All @@ -514,22 +520,22 @@ describe('$httpBackend', function() {
$backend = createHttpBackend($browser, createMockXhr);

// request to http://
$backend('POST', 'http://rest_api/create_whatever', null, callback);
$backend('POST', 'http://rest_api/create_whatever', null, noop, callback);
respond(201, '');

expect(callback).toHaveBeenCalled();
expect(callback.mostRecentCall.args[0]).toBe(201);


// request to file://
$backend('POST', 'file://rest_api/create_whatever', null, callback);
$backend('POST', 'file://rest_api/create_whatever', null, noop, callback);
respond(201, '');

expect(callback).toHaveBeenCalled();
expect(callback.mostRecentCall.args[0]).toBe(201);

// request to file:// with HTTP status >= 300
$backend('POST', 'file://rest_api/create_whatever', null, callback);
$backend('POST', 'file://rest_api/create_whatever', null, noop, callback);
respond(503, '');

expect(callback).toHaveBeenCalled();
Expand Down
Loading