mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-03-17 07:40:22 +00:00
feat($http): allow passing custom cache instance per request
You can still use cache: true, which will use $http's default cache.
This commit is contained in:
parent
caeb1bf899
commit
5bbd64ac65
2 changed files with 98 additions and 25 deletions
|
|
@ -92,7 +92,7 @@ function $HttpProvider() {
|
|||
this.$get = ['$httpBackend', '$browser', '$exceptionHandler', '$cacheFactory', '$rootScope',
|
||||
function($httpBackend, $browser, $exceptionHandler, $cacheFactory, $rootScope) {
|
||||
|
||||
var cache = $cacheFactory('$http');
|
||||
var defaultCache = $cacheFactory('$http');
|
||||
|
||||
// the actual service
|
||||
function $http(config) {
|
||||
|
|
@ -226,7 +226,7 @@ function $HttpProvider() {
|
|||
* Represents Request object, returned by $http()
|
||||
*
|
||||
* !!! ACCESS CLOSURE VARS:
|
||||
* $httpBackend, $browser, $config, $log, $rootScope, cache, $http.pendingRequests
|
||||
* $httpBackend, $browser, $config, $log, $rootScope, defaultCache, $http.pendingRequests
|
||||
*/
|
||||
function XhrFuture() {
|
||||
var rawRequest, parsedHeaders,
|
||||
|
|
@ -244,9 +244,15 @@ function $HttpProvider() {
|
|||
// aborted request or jsonp
|
||||
if (!rawRequest) parsedHeaders = {};
|
||||
|
||||
if (cfg.cache && cfg.method == 'GET' && 200 <= status && status < 300) {
|
||||
parsedHeaders = parsedHeaders || parseHeaders(rawRequest.getAllResponseHeaders());
|
||||
cache.put(cfg.url, [status, response, parsedHeaders]);
|
||||
if (cfg.cache && cfg.method == 'GET') {
|
||||
var cache = isObject(cfg.cache) && cfg.cache || defaultCache;
|
||||
if (200 <= status && status < 300) {
|
||||
parsedHeaders = parsedHeaders || parseHeaders(rawRequest.getAllResponseHeaders());
|
||||
cache.put(cfg.url, [status, response, parsedHeaders]);
|
||||
} else {
|
||||
// remove future object from cache
|
||||
cache.remove(cfg.url);
|
||||
}
|
||||
}
|
||||
|
||||
fireCallbacks(response, status);
|
||||
|
|
@ -333,19 +339,43 @@ function $HttpProvider() {
|
|||
headers = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},
|
||||
defHeaders.common, defHeaders[lowercase(cfg.method)], cfg.headers);
|
||||
|
||||
var fromCache;
|
||||
if (cfg.cache && cfg.method == 'GET' && (fromCache = cache.get(cfg.url))) {
|
||||
$browser.defer(function() {
|
||||
parsedHeaders = fromCache[2];
|
||||
fireCallbacks(fromCache[1], fromCache[0]);
|
||||
});
|
||||
} else {
|
||||
var cache = isObject(cfg.cache) && cfg.cache || defaultCache,
|
||||
fromCache;
|
||||
|
||||
if (cfg.cache && cfg.method == 'GET') {
|
||||
fromCache = cache.get(cfg.url);
|
||||
if (fromCache) {
|
||||
if (fromCache instanceof XhrFuture) {
|
||||
// cached request has already been sent, but there is no reponse yet,
|
||||
// we need to register callback and fire callbacks when the request is back
|
||||
// note, we have to get the values from cache and perform transformations on them,
|
||||
// as the configurations don't have to be same
|
||||
fromCache.on('always', function() {
|
||||
var requestFromCache = cache.get(cfg.url);
|
||||
parsedHeaders = requestFromCache[2];
|
||||
fireCallbacks(requestFromCache[1], requestFromCache[0]);
|
||||
});
|
||||
} else {
|
||||
// serving from cache - still needs to be async
|
||||
$browser.defer(function() {
|
||||
parsedHeaders = fromCache[2];
|
||||
fireCallbacks(fromCache[1], fromCache[0]);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// put future object into cache
|
||||
cache.put(cfg.url, self);
|
||||
}
|
||||
}
|
||||
|
||||
// really send the request
|
||||
if (!cfg.cache || cfg.method !== 'GET' || !fromCache) {
|
||||
rawRequest = $httpBackend(cfg.method, cfg.url, data, done, headers, cfg.timeout);
|
||||
}
|
||||
|
||||
$rootScope.$broadcast('$http.request', self);
|
||||
$http.pendingRequests.push(self);
|
||||
return this;
|
||||
return self;
|
||||
};
|
||||
|
||||
// just alias so that in stack trace we can see send() instead of retry()
|
||||
|
|
|
|||
|
|
@ -779,16 +779,22 @@ describe('$http', function() {
|
|||
|
||||
describe('cache', function() {
|
||||
|
||||
var cache;
|
||||
|
||||
beforeEach(inject(function($cacheFactory) {
|
||||
cache = $cacheFactory('testCache');
|
||||
}));
|
||||
|
||||
function doFirstCacheRequest(method, respStatus, headers) {
|
||||
$httpBackend.expect(method || 'GET', '/url').respond(respStatus || 200, 'content', headers);
|
||||
$http({method: method || 'GET', url: '/url', cache: true});
|
||||
$http({method: method || 'GET', url: '/url', cache: cache});
|
||||
$httpBackend.flush();
|
||||
}
|
||||
|
||||
it('should cache GET request', function() {
|
||||
it('should cache GET request when cache is provided', function() {
|
||||
doFirstCacheRequest();
|
||||
|
||||
$http({method: 'get', url: '/url', cache: true}).on('200', callback);
|
||||
$http({method: 'get', url: '/url', cache: cache}).on('200', callback);
|
||||
$browser.defer.flush();
|
||||
|
||||
expect(callback).toHaveBeenCalledOnce();
|
||||
|
|
@ -796,11 +802,28 @@ describe('$http', function() {
|
|||
});
|
||||
|
||||
|
||||
it('should not cache when cache is not provided', function() {
|
||||
doFirstCacheRequest();
|
||||
|
||||
$httpBackend.expect('GET', '/url').respond();
|
||||
$http({method: 'GET', url: '/url'});
|
||||
});
|
||||
|
||||
|
||||
it('should perform request when cache cleared', function() {
|
||||
doFirstCacheRequest();
|
||||
|
||||
cache.removeAll();
|
||||
$httpBackend.expect('GET', '/url').respond();
|
||||
$http({method: 'GET', url: '/url', cache: cache});
|
||||
});
|
||||
|
||||
|
||||
it('should always call callback asynchronously', function() {
|
||||
doFirstCacheRequest();
|
||||
$http({method: 'get', url: '/url', cache: true}).on('200', callback);
|
||||
$http({method: 'get', url: '/url', cache: cache}).on('200', callback);
|
||||
|
||||
expect(callback).not.toHaveBeenCalledOnce();
|
||||
expect(callback).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
|
|
@ -808,7 +831,7 @@ describe('$http', function() {
|
|||
doFirstCacheRequest('POST');
|
||||
|
||||
$httpBackend.expect('POST', '/url').respond('content2');
|
||||
$http({method: 'POST', url: '/url', cache: true}).on('200', callback);
|
||||
$http({method: 'POST', url: '/url', cache: cache}).on('200', callback);
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(callback).toHaveBeenCalledOnce();
|
||||
|
|
@ -820,7 +843,7 @@ describe('$http', function() {
|
|||
doFirstCacheRequest('PUT');
|
||||
|
||||
$httpBackend.expect('PUT', '/url').respond('content2');
|
||||
$http({method: 'PUT', url: '/url', cache: true}).on('200', callback);
|
||||
$http({method: 'PUT', url: '/url', cache: cache}).on('200', callback);
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(callback).toHaveBeenCalledOnce();
|
||||
|
|
@ -832,7 +855,7 @@ describe('$http', function() {
|
|||
doFirstCacheRequest('DELETE');
|
||||
|
||||
$httpBackend.expect('DELETE', '/url').respond(206);
|
||||
$http({method: 'DELETE', url: '/url', cache: true}).on('206', callback);
|
||||
$http({method: 'DELETE', url: '/url', cache: cache}).on('206', callback);
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(callback).toHaveBeenCalledOnce();
|
||||
|
|
@ -843,7 +866,7 @@ describe('$http', function() {
|
|||
doFirstCacheRequest('GET', 404);
|
||||
|
||||
$httpBackend.expect('GET', '/url').respond('content2');
|
||||
$http({method: 'GET', url: '/url', cache: true}).on('200', callback);
|
||||
$http({method: 'GET', url: '/url', cache: cache}).on('200', callback);
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(callback).toHaveBeenCalledOnce();
|
||||
|
|
@ -858,7 +881,7 @@ describe('$http', function() {
|
|||
expect(headers('server')).toBe('Apache');
|
||||
});
|
||||
|
||||
$http({method: 'GET', url: '/url', cache: true}).on('200', callback);
|
||||
$http({method: 'GET', url: '/url', cache: cache}).on('200', callback);
|
||||
$browser.defer.flush();
|
||||
expect(callback).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
|
@ -870,10 +893,27 @@ describe('$http', function() {
|
|||
expect(status).toBe(201);
|
||||
});
|
||||
|
||||
$http({method: 'get', url: '/url', cache: true}).on('2xx', callback);
|
||||
$http({method: 'get', url: '/url', cache: cache}).on('2xx', callback);
|
||||
$browser.defer.flush();
|
||||
expect(callback).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
|
||||
it('should use cache even if request fired before first response is back', function() {
|
||||
$httpBackend.expect('GET', '/url').respond(201, 'fake-response');
|
||||
|
||||
callback.andCallFake(function(response, status, headers) {
|
||||
expect(response).toBe('fake-response');
|
||||
expect(status).toBe(201);
|
||||
});
|
||||
|
||||
$http({method: 'GET', url: '/url', cache: cache}).on('always', callback);
|
||||
$http({method: 'GET', url: '/url', cache: cache}).on('always', callback);
|
||||
|
||||
$httpBackend.flush();
|
||||
expect(callback).toHaveBeenCalled();
|
||||
expect(callback.callCount).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
|
@ -903,10 +943,13 @@ describe('$http', function() {
|
|||
});
|
||||
|
||||
|
||||
it('should remove the request when served from cache', function() {
|
||||
it('should update pending requests even when served from cache', function() {
|
||||
$httpBackend.when('GET').respond(200);
|
||||
|
||||
$http({method: 'get', url: '/cached', cache: true});
|
||||
$http({method: 'get', url: '/cached', cache: true});
|
||||
expect($http.pendingRequests.length).toBe(2);
|
||||
|
||||
$httpBackend.flush();
|
||||
expect($http.pendingRequests.length).toBe(0);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue