I'm building a news app. I refresh a div with the class of .new_feed every 10 seconds, to check for new updates, and when there is it shows up. Now the problem is, when there is a new feed in it, and the 10 seconds is up, and you don't click to see, and wait for 40 seconds before you click,it brings up 4 records instead of 1. I think the problem has to do with caching.
Refresh script that gets the headline of the news
$(document).ready(function() {
$.ajaxSetup({ cache: false });
setInterval(function() {
$('.new_feed').load('headline.asp');
}, 10000);
});
Getting the feeds
$(function() {
//More Button
$('.more2').live("click",function() {
var u_pic_id = $(this).attr("id");
if (u_pic_id) {
$("#more2"+u_pic_id).html('<img src="moreajax.gif" />');
$.ajax({
type: "POST",
url: "show_more.asp",
data: "lastmsg="+ id,
cache: false,
success: function(html) {
$("ol#updates2").append(html);
$("#more2"+id).remove();
}
});
}
return false;
});
});
</script>
HTML
<div id="more2<%=(rs_ncount_id.Fields.Item("id").Value)+1%>" class="morebox2">
<a href="#" class="more2" id="<%=(rs_ncount_id.Fields.Item("id").Value)+1%>">
Load New Feeds
</a>
</div>
Using HTTP header
You have to set the Cache-Control HTTP/1.1 header at the server side. This is the recommended approach.
Using a nonce in the request
However you can also use a hacky solution, if you can't change the server settings. Use a nonce in the request:
$('.new_feed').load('headline.asp?' + nonce);
Because it will look like a different request to the browser, it will ignore the cached value.
The simplest solution for a nonce is using the current time:
var date = new Date();
var nonce = date.getMilliseconds();
I had an answer written up that pointed out the cache:false option for $.ajax but upon reviewing your OP I realized you were already using it. The documentation indicates the cache:false option will only append a timestamp on GET requests (and POST requests for IE8).
Since you're using a POST its unlikely the cache:false option is actually going to help (unless you're using IE8?). Instead, like #meskobalazs states you'll need to create and append a nonce.
One way to implement this might be like:
function getValues(id) {
var url = 'myUrl?id=' + id;
$.ajax({
type: "POST",
url: url + '&_=' + (new Date()).getTime()
}).done(function(response) {
// do stuff
})
}
Of course if you have access to the server the appropriate way to handle this would be to correctly set the response headers. You may also consider using a more RESTful approach where the GET verb and route is used to request data.
Related
I use ajax in Arcgis Javascript (if you are familiar, i just inform you that i use it, never mind) to select some data and show it in modal window, but i have problem, e.g. i clicked several feature on map (e.g. 3 features) and on each click i get different info, but if i click info button again and again it shows these selected features one by one even though i have selected different feature on map, it stores data and does not show correct info when i continue click and get info from a map.
I use 'cache: false' in $.ajax but it's not working.
Any help please, i checked this article, but it didn't help.
here is a piece of code i use
$(document).on('click', '#vf', function () //
{
var folder_name = 'inv_images/' + graphic.attributes.Wis_invent_N;
var action = "fetch_files";
$.ajax({
url: "action.php",
method: "POST",
data:{
action:action, folder_name:folder_name,
},
cache: false,
success: function(data)
{
$('#file_list').html(data);
$('#filelistModal').modal('show');
}
})
});
});
If it's the browser that's caching the ajax request (ex. IE does that) then you can change the actual request that's done by adding a timestamp to the url:
...
$.ajax({
url: "action.php?t=" + new Date().getTime(),
...
The backend should ignore the extra t parameter, but your browser thinks it's a different url therefore doesn't use the cached response.
I am working on new app in javascript. What I need is that whenever latest news is added to the database at the backend then the front end should know about it and update that area asynchrnously. What is the best and efficient way to achieve this in JavaScript and/or jQuery?
I would recommend using long polling. With a quick Google search you should be able to get up and running. For example here.
use Window.setInterval() to reload the page for specific interval of time so that the news gets updated
$.ajax Documentation
make a function get_news which contains ajax request which well get updated content from the server.
setInterval(get_news, 1000) will call the function get_news after every 1000 ms
function get_news() {
$.ajax({
type: "POST",
url: url,
data: data,
success: function (data) {
$('#content').html(data);
}
dataType: dataType
});
}
setInterval(get_news, 1000); //1000 ms
I've made an ajax call with a jQuery.everyTime() function.
I got a combo box where i select some graph names and dynamically calls to an ajax function, returns a json and creates the chart in the View every 10 seconds.
Everything goes fine but when i select another graph name and click in the function, i don't only have the new graph but i got the old one as well (as a request), so every time i click in a new one (let's say 8 names) i would get 8 requests simultaneously and ofc the latest will be shown (but if you check in firebug you will see the 8 requests).
This is my ajax function:
var selected = $("#name_list :selected").val();
$(".title_graph").text(selected);
var j = jQuery.noConflict();
j("#hour").everyTime(10000,function(i){
j.ajax({
type: "GET",
url: "getchartdata?graphName=" + selected +"&subgroup=hour",
cache: false,
success: function(jsonData){
var data = eval(jsonData);
drawChart(data, data[0][0], data[0][1]);
}
})
});
I would like to cancel previus ajax calls without having to refresh the page. Am i able to do that? like put some kind of "stop" at the very beginning of the function, don't really know. I've seen ajaxName.abort() solution, but i believe it couldn't be applied to what i need.
Thanks in advance.
ADDED:
This is how it looks now with Travis' suggestion:
function getChartsByGraphName() {
var selected = $("#name_list :selected").val();
var ajaxCallHour;
$(".title_graph").text(selected);
var j = jQuery.noConflict();
j("#hour").everyTime(10000,function(i){
ajaxCallHour && ajaxCallHour.abort();
ajaxCallHour = j.ajax({
type: "GET",
url: "getchartdata?graphName=" + selected +"&subgroup=hour",
cache: false,
success: function(jsonData){
var data = eval(jsonData);
drawChart(data, data[0][0], data[0][1]);
}
})
});
}
But it's still sending old ajax requests.
See this answer: Abort Ajax requests using jQuery
Create a variable outside of your everyTime that stores the xhr, then stop it before issuing a new one.
var xhr;
j("#hour").everyTime(10000,function(i){
xhr && xhr.abort();
xhr = j.ajax();
});
Building a social network, I'm trying to fetch live notifications. Currently, the site sends an AJAX request every few seconds using setInterval. It looks something like this:
setInterval ( function(){
url = base_dir+"/ajax/file.php";
data = "data=someData";
$.ajax({
type: "POST",
url: url,
data: data,
dataType: "json",
beforeSend: function(x) {
if(x && x.overrideMimeType) {
x.overrideMimeType("application/json;charset=UTF-8");
}
},
success: function(JSON){
// retrieve data here
}
});
}, 5000);
That works perfectly, but I'm very worried about that creating servers overload. I tried the comet technique but for some reason it sends much more requests than the above code.
Is there any other more useful technique for pushing this data live?
EDIT:
For implementing long polling I used the following (used the example mentioned here: http://techoctave.com/c7/posts/60-simple-long-polling-example-with-javascript-and-jquery):
(function poll(){
url = base_dir+"/ajax/file.php";
data = "data=someData";
$.ajax({
type: "POST",
url: url,
data: data,
dataType: "json",
beforeSend: function(x) {
if(x && x.overrideMimeType) {
x.overrideMimeType("application/json;charset=UTF-8");
}
},
success: function(JSON){
// retrieve data here
},
complete: poll,
timeout: 5000
});
})();
There's a possibility that I might not get the comet principle right.
PHP code:
// Checks for new notifications, and updates the title and notifications bar if there are any
private static function NotificationsCounter (){
//self::$it_user_id = query that retrieves my id for further checks;
//$friend_requests_count = query that retrieves the friend requests count;
//$updates_count = query that retrieves the updates count;
$total_notifications = $friend_requests_count+$updates_count;
if ($total_notifications > 0) $addToTitle = "(".$total_notifications.")";
else $addToTitle = "";
if ($updates_count > 0) $counterHTML = "<span class='notification_counter' id='updates_counter' style='float: right;'>".$updates_count."</span>";
else $counterHTML = "";
$data = array("counter"=>$total_notifications,"addToTitle"=>$addToTitle,"counterHTML"=>$counterHTML,);
echo json_encode($data); // parse to json and print
}
Since Facebook uses PHP as well, how do they do it?
You should use websockets. You can connect to the server and register onmessage handler. Whenever the server has anything to be send to client, your handler will get invoked. No timeout needed.
Check for websocket support in your browser. As of now, only Chrome, Opera and Safari support them.
if ('WebSocket' in window){
/* WebSocket is supported. You can proceed with your code*/
} else {
/*WebSockets are not supported. Try a fallback method like long-polling etc*/
}
Connecting
var connection = new WebSocket('ws://example.org:12345/myapp');
Handlers
connection.onopen = function(){
console.log('Connection open!');
}
connection.onclose = function(){
console.log('Connection closed');
}
connection.onmessage = function(e){
var server_message = e.data;
console.log(server_message);
}
Documentation: http://www.developerfusion.com/article/143158/an-introduction-to-websockets/
Websockets will be the way to go once they are more universally implemented across the major browsers - I would guess a minimum of 5 years.
The last I heard Facebook chat uses comet and a whole bunch of servers. If you want something more lightweight I can think of two options.
Reduce the polling interval. This is strictly a UI issue - users may have a perfectly acceptable experience with intervals as long as a couple minutes. The only way to know for certain is through user testing, but polling every 5 seconds is probably overkill. No matter what you choose as the optimal interval, this does give you an quick way to scale if you are getting hammered - just crank up the interval until the servers stop melting.
Use HTTP validation caching. You can make the requests more lightweight if the server only returns a response body when the content has changed since the last request. You will have to build something custom using ETag or Last-Modified headers and a lightweight modification checking system on the server, but it might save you a few bytes.
I am serving my website from mywebsite.com. I host images on flickr so all images are loaded in the user's browser via get requests to flickr. Many of my websites users access mywebsite.com from corporate networks, which block access to flickr.com. This means users get very annoying blank placeholders instead of the images. I get the same problem with the Facebook like button. This makes my site look very unattractive to such users.
Is there a way I can run a client side script which will check if flickr.com, facebook.com, etc. are accessible. If not I could change the href attribute of the image to load from an alternate source, or replace with a standard image explaining that their network is blocking access. I could also remove the Facebook like button.
I thought an XML http request would do the trick, but then I'd hit cross domain issues I think. I guess I could also set up a proxy to serve the images, but I don't want to do that; the idea of this is that flickr takes the bandwidth hit.
TLDR: How do I determine if flickr.com is accessible from a user's browser, using client side technology.
You could try this...
var image = new Image();
image.onerror = function() {
var images = document
.getElementById('flicker-images')
.getElementsByTagName('img');
for (var i = 0, imagesLength = images.length; i < imagesLength; i++) {
images[i].src = 'images/flickr_is_blocked.gif';
}
};
image.src = 'http://flickr.com/favicon.ico';
Hacky, but it seems to work. However it relies that the favicon.ico 404ing means the main site is.
jsFiddle.
Working example: http://jsfiddle.net/peeter/pW5wB/
JS:
$(document).ready(function() {
var callbackOnSuccess = function(src) {
alert("Successfully loaded " + src);
return false;
};
var callbackOnFailure = function(src) {
alert("Failed loading " + src);
// Here you can do whatever you want with your flickr images. Lets change the src and alt tags
$(".flickr").attr("src", "flickr_is_blocked.gif");
$(".flickr").attr("alt", "Flicker is blocked");
// Lets change the parents href to #
$(".flickr").parent().removeAttr("href");
return false;
};
checkAvailability("http://flickr.com/favicon.ico", callbackOnSuccess, callbackOnFailure);
});
function checkAvailability(src, callbackSuccess, callbackFailure) {
$("<img/>").attr("src", src).load(function() {
callbackSuccess(src);
}).error(function() {
callbackFailure(src);
});
}
HTML:
<a href="http://flickr.com/favicon.ico">
<img class="flickr" src="http://flickr.com/favicon.ico" alt="Flickr"/>
</a>
For facebook you can simply include the Facebook JS API and then test if one of the objects/functions it exports exists.
It would be better if you did not (ab-)use external hosts for your stuff. If you want a CDN, better use a real one...
Flickr and Facebook both have APIs that support JSONP, so cross-domain isn't an issue.
i.e. Here's a request that just echoes some dummy data from flickr's API.
$.ajax({
url: "http://www.flickr.com/services/rest/?jsoncallback=?",
dataType: 'json',
data: {method: "fickr.test.echo", format: "json", api_key: "02de950d65ec54a7a057af0e992de790"},
success: callback
});
You can't reliably set error handlers on a jsonp reqest, so show a "loading" image until that success callback gets called. Set some timeout that will show an error message if the response doesn't come back fast enough.
This works, but timeout must be set!
$.ajax({
url: "http://example.com/ping.html",
type: 'GET',
dataType: 'jsonp',
jsonpCallback: 'jsonCallback',
timeout: 1000,
cache: false,
success: function(response) {
console.log("SERVER UP!");
},
error: function(e) {
console.log("SERVER DOWN!");
}
});
ping.html should return:
jsonCallback({response:'PONG'});