how does Angular $http cache key get created - angularjs

It does not specific in the Angular docs how $http checks the cache for existing keys.
For example, when I do:
$http.get("/search/11", { cache: true });
The cache will obviously work.
But what if i do
$http.get("/search", { cache: true, params: { age: 11 } });
Or the more complicated
$http.post("/search", objectParams, { cache: true });
Will it by pass cache if I change one of the properties of objectParams?
The more general question is, how does Angular know when to serve from cache vs make a new request? Does it compare just the url, the params, the postload, or all of them?

The cache key is the url built by buildUrl function in http.js(src):
url = buildUrl(config.url, config.params);
which creates a url with a query string part : ?key1=val1&key2=val2 out of config.params.
So,
$http.get("/search", {cache: true, params: {key1: "val1"}})
// or
$http.post("/search", postData, {cache: true, params: {key1: "val1"}})
will have a cache key of "/search?key1=val1"

Related

Trouble understanding how angularjs $httpDefaultCache, $cacheFactory and how to access that data

I'm having to inline all resources into one file and this includes all the data that my application uses. With a gulp process, I've been able to create a $cacheFactory with all the data:
angular.module('app').run('$cacheFactory', '$http', function($cacheFactory, $http){
var $httpDefaultCache = $cacheFactory.get('$http');
$httpDefaultCache.put('/data/names.json',{...});
$httpDefaultCache.put('/data/places.json',{...});
});
My understanding of how to access this instead of making a call externally (file) may be incorrect.
I thought that by setting $httpProvider.defaults.cache = true, that my request to the endpoints of above would use the default cache.
.config(['$httpProvider', function ($httpProvider) {
$httpProvider.defaults.cache = true;
}]);
Instead I get an error of
https://.../data/names.json 404 (Not Found)
As if it is looking within the the client and not in angular's cache. The type is also an xhr.
data.load(names, '/data/names.json');
...
function load(broadcastName, url, force){
if(!isLoaded[broadcastName] && !force){
console.log('Loading name data from', url);
// Make the http GET request
http({
method: 'GET',
url: url,
cache: true
}).then(function success(response){
console.log("response: ", response)
...
})
Had to create a custom http request that perfectly imitates angular $http service. It is used in several other applications we have, so I know it works. Only thing that has been added for this implenation is cache:true.
I've looked at several other questions that were similar, but I am still not understanding how it is working. How does using http default cache work? And is there something I should be aware of that I may be glossing over?
I hope this makes sense.
There's no special term for $http cache like '$httpDefaultCache'. It works like you expect it to work. You set either $httpProvider.defaults.cache or cache request option to true, and the response is retrieved from $http cache, which is available by default as $cacheFactory.get('$http').
Cache is just key/value storage. If request URL doesn't match a key completely, cache won't be used.
Here's an example how it works:
$cacheFactory.get('$http').put('/foo', 'foo');
$http({ url: '/foo', cache: true })
.then(result => {
$scope.foo = result.data;
})
.catch(result => console.error(result))

$resource caching: What's the difference between cache: true and cache: obj

As the title states, I'm using a $resource object to do a GET request.
Can someone who has in-depth knowledge explain the difference when setting
cache: true
query: {
method: 'GET',
cache: true
}
VS having something like:
var theCache = $cacheFactory('myCache');
and using that cache object on the resource by doing this:
query: {
method: 'GET',
cache: theCache
}
By passing the true parameter, you're telling angular to use the default (global) $http cache, which means the response will be cached and every next request made through $http or $resource (which is a high-level abstraction over the $http) will be served from cache (no extra requests to the server). The key for this request in the $http cache is the full-path URL. You can obtain the default $http cache instance using the $cacheFactory:
var cache = $cacheFactory.get('$http');
Now, if you want to create a resource-specific cache you create it using the $cacheFactory and tell the $http or $resource to use it:
var myCache = $cacheFactory.get('myCache');
$http.get('/api/users.json', {
cache: myCache
});
// or
$resource('/api/users.json', null, {
query: { cache: myCache }
});
This way no other requests will be sharing this cache anymore. Additionally, you can specify the capacity of this cache while instantiating it, or clear it whenever you need to without affecting the other service.

How can i Prevent caching in angular?

I want to prevent caching in angular.For that i set the cache property to
false.After doing this i request the same url .But didn't send that request
to my server.
Used code for preventing,
$http({
cache : false,
method: "GET",
url :"myurl";
}).success(function(data) {
}).error(function(data) {
});
And code used for remove cache,
var $httpDefaultCache = $cacheFactory.get('$http');
$httpDefaultCache.remove('myurl');
$http({
cache : false,
method: "GET",
url :"myurl";
}).success(function(data) {
}).error(function(data) {
});
can u help me?Please
You could pass the dummy parameter in the URL so that URL become an unique by adding data into it. Passing dummy parameter in params array will not harm the $http get call.
$http({
method: 'GET',
url: 'myurl',
params: { 'dummy': new Date().getTime() }
})
This will ensure caching will not be done for your url.
Best option would be disable caching on server side link here

withCredentials oboe request

I am currently working with a Neo4j graph database that offers REST url's for free. And I am trying to hook it up to a angular module that provides Oboe client side streaming: https://github.com/RonB/angular-oboe
I am trying to better understand how to add username:password credentials in my request header in an effort to transcribe this curl command
> curl --user username:password http://localhost:7474/auth/list
https://github.com/neo4j-contrib/authentication-extension
In the Usage section of the angular-oboe README, it outlines parameters for the request
$scope.myData = Oboe({
url: '/api/myData',
pattern: '{index}',
pagesize: 100
});
I have a hunch to add a line for withCredentials as listed on the Oboe repo
https://github.com/jimhigson/oboe.js-website/blob/master/content/api.md
oboe({
url: String,
method: String, // optional
headers: Object, // optional
body: String|Object, // optional
cached: Boolean, // optional
withCredentials: Boolean // optional, browser only
})
But I'm not sure where to put the username:password pair.
Any help you could offer would be greatly appreciated in collaboration.
The angular-oboe service passes all parameters to the Oboe function so you can specify a headers parameter. To make sure authentication is allowed on the request specify withCredentials: true.
Basic authentication can be achieved by:
.controller('StreamingCtrl', function($scope, Oboe) {
$scope.contacts = [];
// the contacts streamed
$scope.contacts = Oboe({
url: 'http://some.restfull.srv/contacts',
pattern: '{contactid}',
pagesize: 100,
withCredentials: true,
headers: {
// Base 64 encoded Basis authentication
Authorization: 'Basic ' + btoa('username:password')
}
});
})
The btoa function will Base 64 encode the username and password.
Edit:
The angular-oboe factory has been altered since the first answer and is returning a promise instead of the array of json objects.
This is how to use the latest version:
angular.module('MyApp')
.controller(['$scope', 'Oboe', function($scope, Oboe) {
$scope.myData = [];
Oboe({
url: '/api/myData',
pattern: '{index}',
withCredentials: true,
headers: {
Authentication: 'Basic ' + btoa('yourusername:yourpassword')
}
}).then(function() {
// finished loading
}, function(error) {
// handle errors
}, function(node) {
// node received
$scope.myData.push(node);
});
}]);

How to refresh / invalidate $resource cache in AngularJS

I have a simple User $resource that uses the default $http cache implementation like so:
factory('User', function($resource){
return $resource(endpoint + '/user/current/:projectId', {},
{get:
{
cache: true,
method: 'GET'
}
}
);
})
This works very well, i.e. my server is only called once in my application, then the value is fetched from cache.
But I need to refresh the value from the server after a certain operation. Is there an easy way to do that?
Thanks.
Keep the boolean and get the $http cache:
var $httpDefaultCache = $cacheFactory.get('$http');
Then you can control it like any another cache made with $cacheFactory, a usage instance provided below:
$httpDefaultCache.remove(key);
// Where key is the relative URL of your resource (eg: /api/user/current/51a9020d91799f1e9b8db12f)
Instead of using a boolean argument in the cache property of each action you can pass on a cache instance created with $cacheFactory which you can have more control over (i.e. clear the cache).
Example usage:
app.factory('Todos', function($resource, $cacheFactory) {
var cache = $cacheFactory('todo');
return $resource(apiBaseUrl + '/todos/:id', { id: '#id' }, {
'get': { method: 'GET', cache: cache },
'query': { method: 'GET', cache: cache, isArray: true }
});
});
I came across this thread looking for something similar, but found that $resource will manage the cache for you automatically, so there's no need to force the cache to be cleared.
The idea is that if you have a resource that you can query, that query response will be cached, but if you save something for that same resource, the previously cached data must be invalid, so it is cleared for you. It makes sense that it would work this way.
Here's some code I use to do this (you can ignore the possibly odd-looking factory creation part and pay attention to the "class" body).
'use strict';
sampleApp.players.$ng.factory('sampleApp.players.PlayerService', [
'$log',
'$resource',
sampleApp.players.PlayerService = function ($log, $resource) {
var service = {};
$log.info('Creating player resource.');
var Player = $resource('/api/players', {}, {query: {
isArray: true,
cache: true,
method: 'GET'
}});
service.addPlayer = function(playerName) {
$log.info('Saving a new player.');
return new Player({name: playerName}).$save();
};
service.listPlayers = function () {
$log.info('Fetching players.');
return Player.query();
};
return service;
}]);
If you call the listPlayers function several times, the first call makes a http get request and all subsequent calls are cached. If you call addPlayer though, a http post is performed as expected, and then the next call to listPlayers will perform a http get (not cached).
This keeps you out of the business of managing someone else's ($http) cache and trying to keep up with which url's are being used for requests and which are clearing caches at the right times.
I suppose the moral of the story here is to work with the library and all will be well... except for any bugs or incomplete features, but Angular doesn't have any of those ;)
p.s. This is all running on AngularJS 1.2.0.

Resources