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

Added invokeApply parameter to $http to skip apply #12556

Closed
wants to merge 2 commits 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
36 changes: 24 additions & 12 deletions src/ng/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -825,6 +825,8 @@ function $HttpProvider() {
* - **responseType** - `{string}` - see
* [XMLHttpRequest.responseType](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#xmlhttprequest-responsetype).
*
* @param {boolean=} invokeApply: if false, skips model dirty checking after request succeeds
*
* @returns {HttpPromise} Returns a {@link ng.$q `Promise}` that will be resolved to a response object
* when the request succeeds or fails.
*
Expand Down Expand Up @@ -920,7 +922,7 @@ function $HttpProvider() {
</file>
</example>
*/
function $http(requestConfig) {
function $http(requestConfig, invokeApply) {

if (!angular.isObject(requestConfig)) {
throw minErr('$http')('badreq', 'Http request configuration must be an object. Received: {0}', requestConfig);
Expand Down Expand Up @@ -956,7 +958,7 @@ function $HttpProvider() {
}

// send request
return sendReq(config, reqData).then(transformResponse, transformResponse);
return sendReq(config, reqData, invokeApply).then(transformResponse, transformResponse);
};

var chain = [serverRequest, undefined];
Expand Down Expand Up @@ -1083,6 +1085,7 @@ function $HttpProvider() {
*
* @param {string} url Relative or absolute URL specifying the destination of the request
* @param {Object=} config Optional configuration object
* @param {boolean=} invokeApply: if false, skips model dirty checking after request succeeds
* @returns {HttpPromise} Future object
*/

Expand All @@ -1095,6 +1098,7 @@ function $HttpProvider() {
*
* @param {string} url Relative or absolute URL specifying the destination of the request
* @param {Object=} config Optional configuration object
* @param {boolean=} invokeApply: if false, skips model dirty checking after request succeeds
* @returns {HttpPromise} Future object
*/

Expand All @@ -1108,6 +1112,7 @@ function $HttpProvider() {
* @param {string} url Relative or absolute URL specifying the destination of the request.
* The name of the callback should be the string `JSON_CALLBACK`.
* @param {Object=} config Optional configuration object
* @param {boolean=} invokeApply: if false, skips model dirty checking after request succeeds
* @returns {HttpPromise} Future object
*/
createShortMethods('get', 'delete', 'head', 'jsonp');
Expand All @@ -1122,6 +1127,7 @@ function $HttpProvider() {
* @param {string} url Relative or absolute URL specifying the destination of the request
* @param {*} data Request content
* @param {Object=} config Optional configuration object
* @param {boolean=} invokeApply: if false, skips model dirty checking after request succeeds
* @returns {HttpPromise} Future object
*/

Expand All @@ -1135,6 +1141,7 @@ function $HttpProvider() {
* @param {string} url Relative or absolute URL specifying the destination of the request
* @param {*} data Request content
* @param {Object=} config Optional configuration object
* @param {boolean=} invokeApply: if false, skips model dirty checking after request succeeds
* @returns {HttpPromise} Future object
*/

Expand All @@ -1148,6 +1155,7 @@ function $HttpProvider() {
* @param {string} url Relative or absolute URL specifying the destination of the request
* @param {*} data Request content
* @param {Object=} config Optional configuration object
* @param {boolean=} invokeApply: if false, skips model dirty checking after request succeeds
* @returns {HttpPromise} Future object
*/
createShortMethodsWithData('post', 'put', 'patch');
Expand All @@ -1170,24 +1178,24 @@ function $HttpProvider() {

function createShortMethods(names) {
forEach(arguments, function(name) {
$http[name] = function(url, config) {
$http[name] = function(url, config, invokeApply) {
return $http(extend({}, config || {}, {
method: name,
url: url
}));
}), invokeApply);
};
});
}


function createShortMethodsWithData(name) {
forEach(arguments, function(name) {
$http[name] = function(url, data, config) {
$http[name] = function(url, data, config, invokeApply) {
return $http(extend({}, config || {}, {
method: name,
url: url,
data: data
}));
}), invokeApply);
};
});
}
Expand All @@ -1199,7 +1207,7 @@ function $HttpProvider() {
* !!! ACCESSES CLOSURE VARS:
* $httpBackend, defaults, $log, $rootScope, defaultCache, $http.pendingRequests
*/
function sendReq(config, reqData) {
function sendReq(config, reqData, invokeApply) {
var deferred = $q.defer(),
promise = deferred.promise,
cache,
Expand Down Expand Up @@ -1276,11 +1284,15 @@ function $HttpProvider() {
resolvePromise(response, status, headersString, statusText);
}

if (useApplyAsync) {
$rootScope.$applyAsync(resolveHttpPromise);
} else {
resolveHttpPromise();
if (!$rootScope.$$phase) $rootScope.$apply();
var skipApply = (isDefined(invokeApply) && !invokeApply);

if (!skipApply) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so if skipApply is true, then resolveHttpPromise will not get called?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that's a mistake.

if (useApplyAsync) {
$rootScope.$applyAsync(resolveHttpPromise);
} else {
resolveHttpPromise();
if (!$rootScope.$$phase) $rootScope.$apply();
}
}
}

Expand Down
71 changes: 52 additions & 19 deletions test/ng/httpSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1013,32 +1013,65 @@ describe('$http', function() {

describe('scope.$apply', function() {

it('should $apply after success callback', function() {
$httpBackend.when('GET').respond(200);
$http({method: 'GET', url: '/some'});
$httpBackend.flush();
expect($rootScope.$apply).toHaveBeenCalledOnce();
});
describe('when invokeApply is undefined', function() {

it('should $apply after success callback', function() {
$httpBackend.when('GET').respond(200);
$http({method: 'GET', url: '/some'});
$httpBackend.flush();
expect($rootScope.$apply).toHaveBeenCalledOnce();
});


it('should $apply after error callback', function() {
$httpBackend.when('GET').respond(404);
$http({method: 'GET', url: '/some'});
$httpBackend.flush();
expect($rootScope.$apply).toHaveBeenCalledOnce();
it('should $apply after error callback', function() {
$httpBackend.when('GET').respond(404);
$http({method: 'GET', url: '/some'});
$httpBackend.flush();
expect($rootScope.$apply).toHaveBeenCalledOnce();
});


it('should $apply even if exception thrown during callback', inject(function($exceptionHandler) {
$httpBackend.when('GET').respond(200);
callback.andThrow('error in callback');

$http({method: 'GET', url: '/some'}).then(callback);
$httpBackend.flush();
expect($rootScope.$apply).toHaveBeenCalledOnce();

$exceptionHandler.errors = [];
}));
});

describe('when invokeApply is defined and falsy', function() {

it('should $apply even if exception thrown during callback', inject(function($exceptionHandler) {
$httpBackend.when('GET').respond(200);
callback.andThrow('error in callback');
it('should not $apply after success callback', function() {
$httpBackend.when('GET').respond(200);
$http({method: 'GET', url: '/some'}, false);
$httpBackend.flush();
expect($rootScope.$apply).not.toHaveBeenCalledOnce();
});

$http({method: 'GET', url: '/some'}).then(callback);
$httpBackend.flush();
expect($rootScope.$apply).toHaveBeenCalledOnce();

$exceptionHandler.errors = [];
}));
it('should not $apply after error callback', function() {
$httpBackend.when('GET').respond(404);
$http({method: 'GET', url: '/some'}, false);
$httpBackend.flush();
expect($rootScope.$apply).not.toHaveBeenCalledOnce();
});


it('should not $apply if exception thrown during callback', inject(function($exceptionHandler) {
$httpBackend.when('GET').respond(200);
callback.andThrow('error in callback');

$http({method: 'GET', url: '/some'}, false).then(callback);
$httpBackend.flush();
expect($rootScope.$apply).not.toHaveBeenCalledOnce();

$exceptionHandler.errors = [];
}));
});
});


Expand Down