Angular $http call 'cache' attribute default values and behavior - angularjs

I am making $http get call in my application. A single page has a need where this call is made thrice asynchronously. When I set cache to true for the http call it works fine ie it does make only one request to the server. Requirement is only to cache them for a shorter period. So I need to make for the entire page one request is hit to server and the subsequent ones are cached and also the next request to the page ie page refresh should make should hit server and cache the fresh response.
For that purpose, I would like to understand what is the default values like how long does the response remains in the $cacheFactory and is the cache type private or public.
I am aware of the alternative solution, what I am looking here is to know what is the time that this get call is cached for?
$http(
{
method: 'POST',
url: '/test/api/component/getItem',
data: {
projectPath : projectPath
}
}
).then(unwrap);

Related

Alternate option for cache : false in state provider

I have used cache:false in my state to avoid templates(html view) caching like below.
.state('index.project_setup', {
url: '/:customerTag/project-setup',
templateUrl: 'app/views/common/customer/projects/setup_projects_wizard.html',
data: { pageTitle: 'Project Setup' },
cache: false
})
After applying changes in to html file, sometimes i need to hard refresh the page instead of just reload. So is it something i am missing or is there any way to accomplish this thing?
There is a difference between Angular template caching and your browser caching.
When Angular loads a template for the first time, it will fire an AJAX request for that template, and then store the HTMLin a service called $templateCache, so if the exact same template is required again, it will skip the AJAX call and will use the HTML stored in $templateCache.
Once you refreshed your page, the $templateCache service is initialized (because all the JS is initialized) and all the cached HTMLs are gone, so again when Angular will require an HTML file for a template, it will fire AJAX call the first time, store it in the $templateCache and then will use the cached HTML from here on out.
Your browser on the other hand, does not "initialize" his cache on every refresh, so if you will request a file that was cached before, the browser will skip the HTTP call and will use his cached version if one is available.
So lets say we need template named x.html, what will happen is the following pseudo code:
if (x.html exists in $templateCache)
return x.html from $templateCache
else
AngularJS perform HTTP GET for x.html
if (browser has x.html cached version)
return x.html from browser cache and don't fire HTTP request
else
fire HTTP request for x.html and return the result
That is way you must "hard reload" your templates every once in a while.
My solution for development, is attaching a changing query string to the template URL, for example:
.state('index.project_setup', {
url: '/:customerTag/project-setup',
templateUrl: 'app/views/common/customer/projects/setup_projects_wizard.html?v=' + Date.now(),
data: { pageTitle: 'Project Setup' },
cache: false
})
That is a simple trick that causes the browser to always fetch the HTML file because the query string is never the same (well, it will be the same for 1 millisecond :)), so every time the browser will get an HTTP request for that HTML, it will not match previous requests and will not use the cache.

AngularJs $http get not working 1st time but does on subsequent invocations

All:
I have an Iframe tag on a simple HTML page and inside this Iframe tag is a HTML form - lets call it a widget. Its a form where the user can enter search criteria and click on a button to obtain the search results. I have decided to use Angularjs to make the necessary DB calls to a REST service that returns the search results back to the widget for display.
In testing this I enter a value in a textbox on the widget, that value being a value that I know exists in a particular table I'm testing against.
Here is my $http get call:
$http
.get('http://localhost/XXXXService/folder/getfolders/' +
$scope.formData.srchterm **==>** mapped to search textbox
).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
//$scope.formData = response;
//$scope.nrdFolderDataArray = response;
console.log('Success retrieving data.');
console.log(response.length);
console.log('response:');
console.log(response);
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
console.log('Error occurred retrieving data.');
console.log(response.status);
console.log('returned data count:');
console.log(response.size);
console.log('response:');
console.log(response);
});
This call is inside a function called "submitForm" that is mapped to the widget with a "ng-submit="submitForm()" attribute on the submit button. And yes there are several log statements so I can try and figure out what is going on here. And what is happening is this: after entering a value in the textbox, THE FIRST TIME the search button is clicked the .get command does not work. I does not make the call to the REST service. I know this because I wrote the REST service and made sure I put in plenty of log statements while doing so and there are no log statements in the log file from the REST service. Instead the errorCallback block runs and I see all those log statements in the console. The "response" (object?) after THE FIRST call looks like this:
Object {data: null, status: 0, config: Object, statusText: ""} Method = GET Status = (canceled) type xhr
Further, in FF there is no response data to view in the Net tab of Firebug upon THE FIRST call, but there is response data to view in all subsequent calls.
So, interestingly enough each subsequent invocation of that $http.get call works! I see log statements in the log file from the REST service method and the successCallback block runs and I can see my data via those console.log messages.
Also, if I were to change the search value in the text box, which would then be THE FIRST TIME we would be searching for data for that new key, once again, the call does not work, but does work on subsequent clicks on the "search" button for that new key value.
I really am not sure if I have a CORS issue here since, other than THE FIRST calls each subsequent $http.get call works like a champ. Its just that very first call or first call after the search key has changed that the $http.get does not want to work.
I have tried setting headers in the .get call and I have tried using
#CrossOrigin(origins = "http://localhost/7001") as per
https://spring.io/guides/gs/rest-service-cors/ but I continue to have this issue on the first time invoking this .get call.
I've been dealing with this issue for way too many hours now and would sure appreciate some input as to why this is happening.
I'm sorry for being verbose here. I wanted to explain my issue thoroughly.
Please help.
Thank you
-g

Angular default $http cache removes after route change

I am using Angular's default $http cache in one of my services. When the user navigates from a view to another one (I am using ui-router), the cache invalidates and all of the items will be removed from it. I want to not invalidate the cache in the whole lifetime of my application.
EDIT:
For example, this factory does not return cached result after navigating to another route and it calls the server api to get the result:
cardModule.factory("myFactory", function ($http) {
return {
getAll: function () {
return $http.get("all", { cache: true })
}
}
});
How to prevent default cache from removing items from itself after a route change?
I found the source of the problem. It was my own fault. I had a code somewhere that clears the cache after the state change. There is no problem with default angular $http cache.
I would leave this as a comment but I don't have enough points yet..
Could you try some form of memoisation? In other words, have a model on the scope, then, if the model is undefined, trigger the $http call? Something like:
var ctrl = this;
ctrl.product = undefined; // or null
if (ctrl.product === undefined) { // or null
$http.get(...).then(function(resp) {
ctrl.product = resp.data;
};
};
This way the model gets initialized, and called just once. A possible downside would be that the if statement may make this inefficient.
I have not tested this, just throwing the idea out there. I am also very interested in this problem.
That should not be related to ui-router or $http. Here are a few things you need to confirm:
Is your server (which is serving your resources) is setting the cache header or not
Make sure you are not using Ctrl + F5 to refresh the page
If you are using Chrome browser, make sure a setting Disable cache is unchecked

How do you update a cached resource in an angular service?

What is a good pattern for updating angular data from a ngResource service that has been cached?
I been trawling posts like this one [1]: How to refresh / invalidate $resource cache in AngularJS, but would be good to hear from angular experts on the right approach for this specific (but pretty general) scenario.
I am looking for a general pattern here. Both in understanding and in implementing angular - I am a novice at it.
I have a pretty standard ngResource service that has a very standard query method, and a custom put method update.
myServices.factory('ThingsService', [
'$resource',
function ($resource) {
return $resource('/api/things/:id', { id: '#id' }, {
query: { method: 'GET', isArray: true, cache: true },
update: {method: 'PUT', cache: true },
});
}]);
I am using it from a controller like this:
$scope.things = ThingsService.query(function (x) {
// must assign these only once data is loaded
$scope.allCount = x.Things.length;
$scope.incomingCount = $filter('filter')(x.Things, { State: 'incoming' }).length;
});
So far so good. The data is returned just fine, and it renders nicely in a dashboard view.
We support in-place-editing and the user can edit the data right there in the dashboard list.
First take a shadow copy of the thing using angular.copy(...) so that we can support buffering of the changes for the user. (just like a dialog box does for a user). Then when they confirm their changes, we call with the shadow copy:
ThingsService.update({ id: currentThing.Id }, { Data: currentThing.Data }, function () {
//TODO: now, if this PUT succeeds,
//I want to update the value of $scope.things array to reflect the changes,
//without going to back to the server for the whole array.
});
This correctly PUTS the changes to the server, which returns an updated thing, but the dashboard view which is bound to the query method is not updated auto-magically. Was kind of hoping angular and the ThingsService and its cache would take care of that for me somehow, you know by updating the cached data. Since the service should know that I just updated one of the items that the service serves up.
So to avoid going all the way back to the server we have told the ThingsService to cache its results, which is a good start. But how are you supposed to update the changed thing in the cached data?
Is there a standard pattern for this kind of update with a ngResource service?
Preferably I wouldn't have to mess with the cache directly. I should not even care that it is cached or how. I just want $scope.things to reflect the posted changes changes.

how to avoid sending multiple request in backbone js. cache is not able clear

ajaxSetup({ cache: false }); to clear application cache. but when i observer network tab in chrome multiple request are firing.
Attached image shows network tab and how the duplicate requests are firing.
Please suggest me how to avoid duplicate request.
By default, backbone uses jQuery.ajax, which means that ajaxSetup({ cache: false }) is from juery.
Below is straight from jquery. Setting cache to false means that it will send out request each time with unique URL (see the timestamp at the end) and therefore not to cache.
===================
cache (default: true, false for dataType 'script' and 'jsonp')
Type: Boolean
If set to false, it will force requested pages not to be cached by the browser. Note: Setting cache to false will only work correctly with HEAD and GET requests. It works by appending "_={timestamp}" to the GET parameters. The parameter is not needed for other types of requests, except in IE8 when a POST is made to a URL that has already been requested by a GET.
===================

Resources