How to prevent refetching AJAX data? - javascript

I'm using javascript but not jQuery.
Let's say I have 3 users in my database [Kim,Ted,Box] and 3 buttons as below:
<button class="user">Kim</button>
<button class="user">Ted</button>
<button class="user">Box</button>
<div id="displayArea"></div>
If a person clicks on any of the buttons it will display the user information in the div.
Assume I click on the Kim button and it uses ajax and displays the information of Kim. And now I click Ted it also calls a new ajax function to get the data. But when I click Kim again I call the new ajax function to get the data rather than get the data from cache or some place. How can I achieve it without getting the data from ajax function if the data is loaded before?
The reason why I need this is because I don't want the user to wait to get the data again that they loaded before.

Add one level of abstraction by creating a function that takes care of the caching and either returns the data from the cache or makes an Ajax request. For example:
var getDataForUser = (function() {
/**
* We use an object as cache. The user names will be keys.
* This variable can't be accessed outside of this function
*/
var cache = {};
/**
* The function that actually fetches the data
*/
return function getDataForUser(user, callback) {
if (cache.hasOwnProperty(user)) { // cache hit
callback(cache[user]);
} else {
// somehow build the URL including the user name
var url = ...;
makeAjaxRequest(url, function(data) { // cache miss
cache[user] = data; // store in cache
callback(data);
});
}
};
}());
Then you make the call
getDataForUser('John', function(data) { /*...*/ });
twice and the second time it will hit the cache.

Related

how to call a get web service from javascript when the data returned by web changes?

I am trying to call a web-service with in javascript and get the data from web-service.
I want to trigger the ajax call again when the data returned by web services changes.
Here is code i tried with, but failed to trigger callback again when data from server changes.
var request=$.get("http://localhost:8080/messanger/webresources/myresource",function(data){
if(data=="something"){
//do something
}
else if(data=="something else"){
//do something else
}
});
When the data from web-services changes, i want to execute the get request again!!!
Please suggest the concept to do this...
I would suggest recursive call of function that calls the service. It is beeing called just as long as the result differs from the previous one. But im still not sure if it is what zou want:)
var previousResult = null;
function callMyService() {
var request = $.get("http://localhost:8080/messanger/webresources/myresource", function (data) {
if (data == previousResult) {
// returned data is the same as last call
}
else {
// save the previous result to global variable
previousResult = data;
// recursive call
callMyService();
}
});
}
Then call is wherever you need to:
callMyService()

Trying to get the newest innerHTML text of a label

I have a function that queries a database for info, when a button is clicked. This info gets written to innerHTML of a label. When this function returns, I read the innerHTML of this label. Problem is, it always returns the old value, not the new value that was pulled from the database. The label on the scree is displaying the correct value, though. When I click the button again, the value that I was expecting on the previous click, is now given. Seems like a timing issue but can't seem to figure it out.
example:
SQL Data - cost = 10
I expect to see 10 alerted to me when I click the button. I get a blank alerted to me, even though 10 is now in the label. When I click the button again, 10 is alerted, but 20 is now in the label.
function getInfo() {
var ctlMonthly = document.getElementById("cellMonthlyCost")
getSQLData(ctlMonthly);
alert(ctlMonthly.innerHTML);
}
function getSQLData(ctlCell){
...
var my_ctlCell = document.getElementById(ctlCell);
$.each(objData.items, function() {
my_ctlCell.innerHTML = this.Param1
});
...
}
Thanks.
you need to add the alert after the data is received from the database. I am assuming that you're sending an ajax request to fetch data. You will be able to get the new value in the callback of you're ajax request function.
Currently what is happening in your code is that
1. getSQLData(ctlMonthly);
// This sends a request to the data base to fetch data
2. alert(ctlMonthly.innerHTML);
// This shows the current value in an alert
3. data is received and shown in the label
This process happens so fast that you don't notice the difference between step 2 and 3.
Is this what you want?
I used a callback function
function getInfo() {
var ctlMonthly = document.getElementById("cellMonthlyCost")
getSQLData(ctlMonthly,alertInfo);
}
function alertInfo(info){
alert(info);
}
function getSQLDate(ctlCell,callbackFn){
...
var my_ctlCell = document.getElementById(ctlCell);
$.each(objData.items, function() {
my_ctlCell.innerHTML = this.Param1;
callbackFn(this.Param1);
});
...
}
to piggyback on Himanshu's answer, your request to your server is async. Meaning javascript will execute the GET request and continue on with the script, when the requests comes back from the server it will run whatever callback you give it. ( i.e. update label tag )
assuming getSQLData is a ajax call or something promised based, something like:
function getSQLData(ctlCell){
return $.get('/sql/data').done(function () {
var my_ctlCell = document.getElementById(ctlCell);
$.each(objData.items, function() {
my_ctlCell.innerHTML = this.Param1
});
});
}
you can change your code to:
function getInfo() {
var ctlMonthly = document.getElementById("cellMonthlyCost")
getSQLData(ctlMonthly)
.done(function () {
alert(ctlMonthly.innerHTML);
});
}
Basically the difference is your telling javascript to alert the innerHTML after the requests comes back from the server.
The more correct answer would be to alert the data straight from the response instead of reading from the DOM.

Can I cache a segment of HTML with javascript?

My scenario:
I have a page—let's call it items.aspx—that has an HTML table that is generated with a $.get() call to my ASP Web API controller. When a user clicks on one of the items in the HTML table, the user is sent to a page representing that item's details—let's call that one itemDetails.aspx. I predict it will be common to view the itemDetails.aspx page and then decide to cancel and redirect back to the items.aspx page.
The problem:
The problem is that each time the items.aspx page is loaded, the ajax call runs again and it takes a couple seconds to populate the table.
The question:
Is it possible to, when the user clicks the item to go to the itemDetails.aspx page, store/cache the HTML output of the table for a limited time? Since I only want this to happen if the user clicks the item link, I figured javascript would be the best tool.
You could use a function that returns a jQuery Promise for the HTML, whether it is loaded from a local cache or an AJAX request.
A simple example:
// Refers to cached HTML when available
var cached;
// Returns a promise for the HTML
function getHtml() {
var defer;
if(cached) {
defer = new Deferred();
defer.resolve(cached);
} else {
defer = $.get(/* ... */);
defer.then(function(response) {
cached = response;
})
}
return defer.promise();
}
Usage:
getHtml().then(function(html) {
$container.html(html);
})
A real implementation would probably do something to prevent concurrent $.get calls, and expire the cache when required.

Knockout.js ko.mapping.toJS not refreshing data in my view

I fetch a json object from the server and populate my view. I then change the data, push it back to the server. I then fetch a new copy of the data hoping it will refresh my view with any changes. However that doesn't happen. TIA
$(document).ready(function() {
var customer_id = get_customer_id();
var data = load_model();
contract_model = ko.mapping.fromJS(data,{});
ko.applyBindings(contract_model);
}
function load_model(){
var url = '/ar/contract_json?contract_id='+get_contract_id();
var data = '';
$.ajax({
type:'GET',
url:url,
async:false,
success: function(returningValue){
data = returningValue;
}
});
return data;
}
This initial load works fine. I then do some stuff and change one of the observables and push that data back to server. Server gets the update and then I do a new fetch of the data so that view will refresh (i know i can pass back the new data in one step but this in code i haven't refactored yet).
function refresh_data(contract_model){
var url = '/ar/contract_json?contract_id='+get_contract_id();
$.post(url,function(data){
console.log(data);
ko.mapping.fromJS(contract_model,{},data);
ko.applyBindings(contract_model);
console.log(ko.mapping.toJS(contract_model))
});
}
function refresh_data(contract_model){
var url = '/ar/contract_json?contract_id='+get_contract_id();
$.post(url,function(data){
console.log(data);
ko.mapping.fromJS(contract_model,{},data);
console.log(ko.mapping.toJS(contract_model))
});
}
function push_model(contract_model,refresh){
var url = '/ar/update_contract';
var data = {'contract':ko.mapping.toJSON(contract_model)}
delete data['lines'];
$.post(url,data,function(return_value){
if (refresh){
refresh_data(contract_model);
};
});
}
The console messages all show the new data coming back but my view never updates.
I believe the problem is with the order of parameters you pass into the ko.mapping.fromJS function when you are updating contract_model.
You have:
ko.mapping.fromJS(contract_model,{},data);
you want:
ko.mapping.fromJS(data, {}, contract_model);
#seth.miller's answer is correct. You can also leave out the middle "options" parameter if your contract_model is the same one that was mapped earlier. If there are only two arguments, ko.mapping.fromJS checks if the second argument has a "__ko_mapping__" property. If so, it treats it as a target, otherwise it treats it as an options object.
Based upon #DBueno's observation - for anyone using typescript I strongly recommend commenting out this method signature from your knockout.mapping.d.ts file.
// fromJS(jsObject: any, targetOrOptions: any): any;
Yes - just comment it out.
You'll then get a compile time error if you try to do :
ko.mapping.fromJS(item.data, item.target);
and you can replace it with the much safer
ko.mapping.fromJS(item.data, {}, item.target);
Safer because whether or not item.target has been previously mapped (and therfore would have a __ko_mapping__ property) it will always copy the properties.

How to cache the result of $.post-request in jQuery?

I have a small jQuery script that gets information by looking at an ID.
What is the best way to prevent that the same data are requested more than once (e.g. what's the best practices for caching in jQuery)?
I have tried to use $.post and $.ajax with option "cache" set to true, but the request is being sent more than once.
Is it better to save collected data and use sets to see whether you'll have to request it or not?
Any ideas and suggestions are welcome!
If it matters, I use ASP.Net MVC on the server-side.
The cache option you saw on the documentation, refers to the browser's cache.
You can implement a pattern of self-memorizing functions in many ways, the goal is that the function result for determined argument (id in your case) is only computed once.
Since you are using an Ajax request, I would suggest you to use a callback argument also, e.g.:
var getInfo = (function () {
var cache = {}; // results will be cached in this object
return function (id, callback) {
if (cache[id] != null) { // if exist on cache
callback(cache[id]);
return;
}
// doesn't exists on cache, make Ajax request and cache it
$.post("info.url", { "id": id }, function (data) {
cache[id] = data; // store the returned data
callback(data);
});
};
})();
Example usage:
getInfo(5, function (data) {
alert(data);
});

Categories

Resources