I wanted to use long polling.
I google it and found many helpful resources, and since many, I am getting confuse which is better.
Following are three code snippets from two place.
https://gist.github.com/jasdeepkhalsa/4353139
// Long Polling (Recommened Technique - Creates An Open Connection To Server ∴ Fast)
(function poll(){
$.ajax({
url: "server",
success: function(data)
{
//Update your dashboard gauge
salesGauge.setValue(data.value);
},
dataType: "json",
complete: poll,
timeout: 30000
});
})();
// The setTimeout Technique (Not Recommended - No Queues But New AJAX Request Each Time ∴ Slow)
(function poll(){
setTimeout(function(){
$.ajax({
url: "server",
success: function(data)
{
//Update your dashboard gauge
salesGauge.setValue(data.value);
//Setup the next poll recursively
poll();
},
dataType: "json"});
}, 30000);
})();
https://github.com/panique/php-long-polling/blob/master/client/client.js
function getContent(timestamp)
{
var queryString = {'timestamp' : timestamp};
$.ajax(
{
type: 'GET',
url: 'http://127.0.0.1/php-long-polling/server/server.php',
data: queryString,
success: function(data){
// put result data into "obj"
var obj = jQuery.parseJSON(data);
// put the data_from_file into #response
$('#response').html(obj.data_from_file);
// call the function again, this time with the timestamp we just got from server.php
getContent(obj.timestamp);
}
}
);
}
My question is which code is long polling best practice?
Which one should I use?
Thanks in advance.
The first approach is better on my opinion:
If server configured for long polling with timeout more than 30000, then with first one you will have breaking request by timeout and a new request will be sent, success() function would not be called
(while complete() will be, also error could be handled in error() like this
error: function(x, t, m) {
if(t==="timeout") {
alert("got timeout");
} else {
alert(t);
}
}
).
While in the second one a new request would be sent after 30000 and so you would have unpredictable behavior on a client side (two requests can receive the same answer, so data could be duplicated).
If server configured for long polling with less than 30000, then in second approach data on a client side would not be updated in time.
If server configured for long polling with 30000, then it should not be any difference.
To summarize: in first approach situation is controllable, while in second one - not always.
Related
I want to update a shell command output each second using AJAX.
However, Chrome CPU usage is too high and output update seems to be updating so fast ( not one second )
Here is the HTML Document:
<script src='jquery-2.2.4.js'></script>
<script>
setInterval(function() {
$.ajax({
url: "test.php",
success: function(data) {
$("body").html(data);
},
async: true
});
}, 1000);
</script>
</body>
And here is the shell command I'm actually using:
system("dir C:");
It would be better to use a setTimeout which will be called after every successful ajax completion.
You could setup also an error handler in the $.ajax because a network fail might happen and call there again the setTimeout(function(){myajaxfunction();},1000);
var myajaxfunction = function() {
$.ajax({
url: "test.php",
success: function(data) {
$("body").html(data);
setTimeout(function(){myajaxfunction()},1000);
},
async: true
});
};
myajaxfunction();
I found the solution. The AJAX request URL was the same URL I requested from which caused an infinite recursive loop.
So what I did is to request it from another PHP page which contains the data I actually need.
I need to make multiple HTTP requests to an external server via $.ajax and as far as my understanding goes, this should be asynchronous meaning that the multiple HTTP requests do not wait until the preceding request is complete before executing another one.
However, I have found that in practice, this does not hold up. I have this function:
function gethttp(i, v) {
var data = new FormData();
data.append("raw", v.raw);
$.ajax({
url: "gethttp.php?cache=" + Math.random(),
type: "POST",
data: data,
cache: false,
dataType: "json",
processData: false,
contentType: false,
success: function(data, textStatus, jqXHR) {
renderdata(i, data);
},
error: function(jqXHR, textStatus, errorThrown) {
renderdata(i, {found: "0", bibs:""});
apply(i, "danger", false);
console.log(jqXHR);
}
});
}
I then use $.each to iterate through an array requests which passes variables i and v to gethttp() for the HTTP request.
$(document).ready(function() {
$.each(requests, function(i, v) {
gethttp(i, v);
});
});
However, this process can take up to 5 minutes depending on the size of my requests array which can range in length anywhere between 5-500 items. My thought process was that this should take roughly 2 seconds because each HTTP request by itself takes that long, but by looping through it like the above, the requests are executed sequentiality and the entire process takes forever.
Do I need to go deploy this with node.js in order to get parallel processing? If so, I would really appreciate good tutorial on the subject. Can I do this with jQuery itself without resorting to node.js?
Thanks
I'm trying to create a real-time website analytics dashboard which creates an open HTTP connection to the server using jQuery/JavaScript asynchronously to poll the server for updates to the data as and when they occur.
The obvious start for this would be to use an XMLHttpRequest object or jQuery's $.ajax method to send a GET or POST request to the server asynchronously requesting some data.
However, beyond sending one request at a time using a setInterval method every 30 seconds I am not sure how to make the connection to the server persistent. Basically, I only want to send one http request and ensure the connection to the server stays open for polling!
My example code with setInterval is as follows:
<div id="analytics"></div>
<script>
var analytics = document.getElementById('analytics');
setInterval(function(){
$.ajax({ url: "http://server.com/", success: function(data){
analytics.innerHTML = data;
}, dataType: "json"});
}, 30000);
</script>
After searching online, this was the answer I was looking for which doesn't use sockets.io nor WebSockets but does use jQuery by taking advantage of its complete method to create an artificial loop:
<div id="analytics"></div>
<script>
var analytics = document.getElementById('analytics');
(function poll(){
$.ajax({ url: "server", success: function(data){
analytics.innerHTML = data;
}, dataType: "json", complete: poll, timeout: 30000 });
})();
</script>
Source is Tian Davis from Technoctave: http://techoctave.com/c7/posts/60-simple-long-polling-example-with-javascript-and-jquery
The javascript below accomplishes the following (this is for a node.js COMET application):
Request is made to the server and held until the server has something to
return.
Once the request returns the data is processed and another
request is immediately made within the callback function of the
success event.
If a timeout occurs (the server had nothing to return within the time frame)
another request is made within the callback function of the error event.
My concern (which I believe is valid) is that the requests are continually added to the callstack, much like a recursive function that never ends. After a while, it results in the browser eventually crashing and becoming unresponsive (at least I think this is the cause).
How can I accomplish the same thing and avoid this problem?
function GetData(){
$.ajax({
url: "admin.html",
type: "POST",
dataType: "json",
contentType: 'text/json',
data: JSON.stringify({
cmd: "getData"
}),
timeout: (60 * 1000),
success: function(data, textStatus, jqXHR){
UpdateScreen(data);
GetData();
},
error: function(jqXHR, textStatus, errorThrown){
if(textStatus == "timeout"){
GetData();
}
}
});
}
No, I'm pretty sure you are OK. The ajax event is asynchronous, so the GetData function will finish and the browser will wait for events, before it calls GetData again from the success handler.
Think of it as the GetData function just defining what to do, not actually doing it. Then it finishes executing (and clears the stack) and browser does those actions.
function GetData(limit){
limit = limit || 0;
$.ajax({
url: "admin.html",
type: "POST",
dataType: "json",
contentType: 'text/json',
data: JSON.stringify({
cmd: "getData"
}),
timeout: (60 * 1000),
success: function(data, textStatus, jqXHR){
UpdateScreen(data);
GetData();
},
error: function(jqXHR, textStatus, errorThrown){
if(textStatus === "timeout" && limit < 20){
GetData(++limit);
} else {
//throw "epic fail"
setTimeout(GetData, 0);
}
}
});
}
Just add a little timeout limit counter. if it gets too big either give up and throw an error or break the call stack by calling setTimeout which is asynchronous.
I'm wondering if your UpdateScreen(data) method is the problem. Is that a recursive function as well? People suggesting that you simply timeout the method doesn't actually fix the problem, it simply aborts the process. I would try logging something like console.log("get data success") and console.log("get data error") in your success and error callbacks respectively. If your log page is full of one message, you know where the GetData() method is continually called. It could be always timing out.
On a side note, you should change your if statement for an error to something like
if(jqxhr.responseText == "timeout"){
getData();
}
see here for explanation why: jQuery Ajax error handling, show custom exception messages
Within jQuery.ajax we have the blessing of setting a timeout in milliseconds and an Error callback to process that timeout.
However, the some people are simply on slow connection, with small amounts of patience. What I want to do is simply display a message stating "This is taking longer than usual".
The Timeout arguement in jQuery won't satisfy this, and setTimeout() does exactly the same thing. How could this be achieved with a simple time check?
OK, this was simple enough.
All I needed to do was actually set up an independent Timout, with a function inside to display whatever message I needed to.
You can still keep in the Timeout/Error Callback for really long extended periods, too.
var timeout = true;
timeout = setTimeout(function() {
if (timeout) {
$("#zendesk-dropbox-error").html("Contacting the Helpdesk is taking longer than usual, try submitting manually?");
}
}, 9000);
// Call for a JSON return from the PHP script
$.ajax({ type: 'GET', url: http://www.example.com, dataType: 'json', cache: false, data: ({ a: 'b' }), timeout: 60000,
success: function(zendesk){
timeout = false;
// Code
},error: function(objAJAXRequest, strError) {
// Code
}
});