refactor($http): change callback matching mechanism

This commit is contained in:
Vojta Jina 2011-10-26 21:16:01 -07:00 committed by Igor Minar
parent feacf608ee
commit 972c3e9be0
2 changed files with 25 additions and 47 deletions

View file

@ -268,55 +268,33 @@ function $HttpProvider() {
* - clear parsed headers * - clear parsed headers
*/ */
function fireCallbacks(response, status) { function fireCallbacks(response, status) {
var strStatus = status + '';
// transform the response // transform the response
response = transform(response, cfg.transformResponse || $config.transformResponse, rawRequest); response = transform(response, cfg.transformResponse || $config.transformResponse, rawRequest);
var regexp = statusToRegexp(status), var idx; // remove from pending requests
pattern, callback, idx;
// remove from pending requests
if ((idx = indexOf($http.pendingRequests, self)) !== -1) if ((idx = indexOf($http.pendingRequests, self)) !== -1)
$http.pendingRequests.splice(idx, 1); $http.pendingRequests.splice(idx, 1);
// normalize internal statuses to 0 // normalize internal statuses to 0
status = Math.max(status, 0); status = Math.max(status, 0);
for (var i = 0; i < callbacks.length; i += 2) { forEach(callbacks, function(callback) {
pattern = callbacks[i]; if (callback.regexp.test(strStatus)) {
callback = callbacks[i + 1];
if (regexp.test(pattern)) {
try { try {
callback(response, status, headers); // use local var to call it without context
var fn = callback.fn;
fn(response, status, headers);
} catch(e) { } catch(e) {
$exceptionHandler(e); $exceptionHandler(e);
} }
} }
} });
$rootScope.$apply(); $rootScope.$apply();
parsedHeaders = null; parsedHeaders = null;
} }
/**
* Convert given status code number into regexp
*
* It would be much easier to convert registered statuses (e.g. "2xx") into regexps,
* but this has an advantage of creating just one regexp, instead of one regexp per
* registered callback. Anyway, probably not big deal.
*
* @param status
* @returns {RegExp}
*/
function statusToRegexp(status) {
var strStatus = status + '',
regexp = '';
for (var i = Math.min(0, strStatus.length - 3); i < strStatus.length; i++) {
regexp += '(' + (strStatus.charAt(i) || 0) + '|x)';
}
return new RegExp(regexp);
}
/** /**
* This is the third argument in any user callback * This is the third argument in any user callback
* @see parseHeaders * @see parseHeaders
@ -392,11 +370,12 @@ function $HttpProvider() {
* .on('2xx', function(){}); * .on('2xx', function(){});
* .on('2x1', function(){}); * .on('2x1', function(){});
* .on('404', function(){}); * .on('404', function(){});
* .on('xxx', function(){});
* .on('20x,3xx', function(){}); * .on('20x,3xx', function(){});
* .on('success', function(){}); * .on('success', function(){});
* .on('error', function(){}); * .on('error', function(){});
* .on('always', function(){}); * .on('always', function(){});
* .on('timeout', function(){});
* .on('abort', function(){});
* *
* @param {string} pattern Status code pattern with "x" for any number * @param {string} pattern Status code pattern with "x" for any number
* @param {function(*, number, Object)} callback Function to be called when response arrives * @param {function(*, number, Object)} callback Function to be called when response arrives
@ -405,14 +384,18 @@ function $HttpProvider() {
this.on = function(pattern, callback) { this.on = function(pattern, callback) {
var alias = { var alias = {
success: '2xx', success: '2xx',
error: '0-2,0-1,000,4xx,5xx', error: '-2,-1,0,4xx,5xx',
always: 'xxx', always: 'xxx,xx,x',
timeout: '0-1', timeout: '-1',
abort: '000' abort: '0'
}; };
callbacks.push(alias[pattern] || pattern); callbacks.push({
callbacks.push(callback); fn: callback,
// create regexp from given pattern
regexp: new RegExp('^(' + (alias[pattern] || pattern).replace(/,/g, '|').
replace(/x/g, '.') + ')$')
});
return this; return this;
}; };

View file

@ -486,7 +486,7 @@ describe('$http', function() {
$httpBackend.flush(); $httpBackend.flush();
if (match) expect(callback).toHaveBeenCalledOnce(); if (match) expect(callback).toHaveBeenCalledOnce();
else expect(callback).not.toHaveBeenCalledOnce(); else expect(callback).not.toHaveBeenCalled();
} }
beforeEach(function() { beforeEach(function() {
@ -620,11 +620,6 @@ describe('$http', function() {
}); });
it('should call "xxx" when 0 status code', function() {
expectToMatch(0, 'xxx');
});
it('should not call "2xx" when 0 status code', function() { it('should not call "2xx" when 0 status code', function() {
expectToNotMatch(0, '2xx'); expectToNotMatch(0, '2xx');
}); });
@ -634,9 +629,9 @@ describe('$http', function() {
expect(status).toBe(0); expect(status).toBe(0);
}); });
$http({method: 'GET', url: '/0'}).on('xxx', callback); $http({method: 'GET', url: '/0'}).on('always', callback);
$http({method: 'GET', url: '/-1'}).on('xxx', callback); $http({method: 'GET', url: '/-1'}).on('always', callback);
$http({method: 'GET', url: '/-2'}).on('xxx', callback); $http({method: 'GET', url: '/-2'}).on('always', callback);
$httpBackend.flush(); $httpBackend.flush();
expect(callback).toHaveBeenCalled(); expect(callback).toHaveBeenCalled();