Can someone explain what this ajax code does? - javascript

Can someone explain what this ajax code does?
function ajaxProgress(){
//Math.random() is for bitchy ie to prevent caching the xml.
$.get('sample.ff?do=progressInfo&type=sampletype&dummy='+Math.random(), { dataType: 'xml'}, function(xml) {
//if the import is running get infos about the progress...
if($('/importProgress/running', xml).text() == 'true') {
//..there are no infos yet, so it was just started..
if($('/importProgress/progress', xml) == null || $('/importProgress/progress', xml).text() == ''){
//do something
}
..........
setTimeout( "ajaxProgress()", 1000);

This function is calling itself recursively every second. It sends an AJAX GET request to Import.ff and passing 3 query string parameters: do=progressInfo, type=sampletype and a random number. This random number is appended to the url because GET requests are cached by browsers and by this it ensures that it gets fresh content from the server on each request.
The server itself sends an XML file as response. This XML file contains some nodes like:
<importProgress>
<running>true</running>
<progress>20</progress>
</importProgress>
So the script parses this XML in the success callback of the AJAX request. It tries to get the values of the running and progress nodes. If running=true then it checks whether there's a progress node and does some processing with it. Finally it calls itself 1 second later using the setTimeout function. And so on.
So basically this script reports progress from some server operation by polling the server at 1 seconds intervals using AJAX GET requests and parsing the response.

Related

Wait till completion of script [ ajax ]

the below code if the ajax call i make to my run.py and then displays the output in a html tag. the script run.py runs for over 2 mins. But in the js script below. as soon as the script has begun to run. the output ( initial lines of the output) will be displayed in the html tag. the remaining part of the script won't be displayed.
$(document).ready(function(){
$(sub).click(function(){
alert("connecting to host")
$.ajax({
type:'POST',
url:'/cgi-bin/run.py',
dataType: 'html',
success:function (z) {
$('#output').html(z);
}
});
}) ;
});
I'd like to know if there is any function in ajax to wait till completion of script (Not just execution of script. but wait till end ) and then display entire output to the html tag.
Here is my python script:
import sys, os
import cgi, cgitb
def __init__(self, address, username, password):
# connects to host
def sendShell(self, command):
#opens shell
def process(self):
while self.shell.recv_ready():
info += self.shell.recv(1024)
output = str(info, "utf8")
print(output)
hostname = "z.com"
password = "yyy"
username = "dd"
connection = ssh(hostname, username, password)
connection.openShell()
connection.sendShell("date");
jQuery.ajax() has an option async: false, however I'd advise against it and just do whatever you need in ajax callbacks. Also, it's deprecated.
Changing the async flag of the $.Ajax function to false is almost correct, yet in your case the script needs to run for long time so you need to consider using Long Polling for such a request.
The reason is because the browsers have max timeout for ajax calls and usually is set to 1 min depending on the browser(so in your case after 1 min the client / browser stops the connection and wants the response, but you want it to wait until its done and only then send the response back).
So to overcome this you will have to send once a 20 sec or once of the max timeout another request to the py script to check if its done.
Code snippet for javascript side:
function isDone(timestamp) {
timestamp = timestamp || null;
$.ajax({
type:'POST',
url:'/cgi-bin/run.py',
dataType: 'json',
data: { "timestamp": timestamp },
timeout: 20000, // Or to whatever the max-timeout is, haven't checked that with jQuery.
success: function (response) {
if (response.done === false) {
isDone(Date.now ());
} else {
// got the results, can continue.
$('#output').html(response.output);
}
}
});
}
isDone();
I'm not sure how the pyton script should look like, if you want you can share it with me and I will try to complete the server side.
Basically what you should do there is to set the timeout of the script to the max, and return the correct response to the client.
JSON response should look like this:
{
"done": true, // or false if the script timed out.
"output": html, // the variable that should contain the output when the py script is done, if its not done just send a null or don't send it back to the client at all.
"timestamp": time.time() // if im not wrong that's how you get timestamp in py
}
Server-side in pseudo code:
Dynamcally or under setting, configure python script execution time to max or rather to 3 min, sense you mentioned it takes 2 min.
if (timestamp === null) { // first ajax call to this script.
- Start long processing task.
- Write the output to a file.
}
do { // check this code block every 1 sec
if (the file you are writing to was created and is complete / unlocked) {
- Read from that file the content, save it into a variable and delete the file from your system.
- Output the above mentioned response with done set to true and the current timestamp.
- Break outside of the loop
}
if (timed out) { // basically check if 20 second passed sense starting timestamp.
- Output the above mentioned response with done set to false and the current timestamp.
- Break outside of the loop.
}
sleep for 1 sec, you don't want to kill your CPU usage.
} while (true)

php jquery ajax incremental output

I have a webpage that calls an AJAX script - ajax.php. I am using JQuery to send the AJAX requests.
The script ajax.php receives some arguments via$_REQUEST, based on that it starts its processing. The processing has multiple steps involved and at the end of the each step I want to send some feedback back to the page - for example:
Step 1 completed
Step 2 completed
....
Once all the steps are completed - the script ajax.php will output a TXT file which I am outputting via:
header('Content-type: text/plain');
header('Content-Disposition: attachment; filename="output.txt"');
My questions are:
I have a div in the page where I want to show the user that Step 1 completed, Step 2 completed, ... If I use JQuery.ajax(), will the .done function called multiple times? If no, whats the best way to handle it? Can I use ob_implicit_flush in PHP to send 'Step x completed 'messages?
Finally, how will I handle the output of .txt file so that user's browser downloads it? I don't want to save the file on the server and then going into hassle of server disk space, cron jobs of deletes, etc.
I have the option of doing multiple AJAX requests - but again I don't want to do this as this will make my code logic pretty complex and I will have to save a lot of data in $_SESSION to be visible across requests which is again something that I don't want to do.
After your AJAX call to kick off your process, you could make another AJAX call in a loop which requests, returns, and presents the current percentage complete until it reaches 100%. Basically, one AJAX call to initiate the process and then a series of calls which check status.
Here is some simple JavaScript to achieve what you want:
<script>
function startProcess() {
//start your long-running process
$.ajax({
type: 'GET',
url: "/longRunningProcess",
async: true,
success:function (data) {
//do something - your long process is finished
}
});
}
function getStatus() {
//check your progress
$.ajax({
type: 'GET',
url: "/checkProgress",
async: true,
success:function (data) {
//assume the data returned in the percentage complete
var percentage = parseInt(data);
//write your status somewhere, like a jQuery progress bar?
if (percentage < 100) {
//if not complete, check again
getStatus();
}
}
});
}
</script>

Javascript not proceeding aynchronously beyond AJAX call

When the user presses the 'Process' button on my application, I would like the application to trigger an AJAX request and then immediately redirect the user to another screen without waiting for the results of the AJAX request. I believe I have coded it appropriately but I notice that the screen is waiting for the AJAX to finish before redirecting. Am I missing something below?
$('#process-btn').on('click', function()
{
// disable the process & cancel buttons to prevent
// double submission or interruption
$('#cancel-btn').addClass('disabled');
$(this).addClass('disabled');
// trigger the AJAX require to process the uploaded file on the server side
$.ajax({
url: $('#form').attr('action'),
type: 'post',
data: $('#form').serialize(),
success: function() {
//on success
}
});
// redirect the user to view list
// this line is not being called immediately -
// this is being called only after AJAX returns
window.location.replace( www_root + 'Home/index' );
});
Because the button you have this handler hooked to is a submit button for a form (per your comments) and you aren't preventing the default behavior of that button, then the form submit will happen immediately and when the submit returns, it will change the page regardless of what your code tries to do.
So, the issue is that the returned form submit was overcoming what your code was trying to do.
You may be living a little dangerously by redirecting before your ajax call has finished. It's possible the browser could drop the ajax connection before the TCP buffers had actually been sent as TCP often has a small delay before sending buffers in order to collect consecutive data into common packets. It would be much safer to either redirect after a short timeout or redirect on the complete event which will be called regardless of ajax success.
If you really want to do the redirect BEFORE the ajax call has completed, you can experiment with the timeout value (shown here as set to 500ms) in this code to see what works reliably in multiple browsers:
$('#process-btn').on('click', function(e) {
// prevent default form post
e.preventDefault();
// disable the process & cancel buttons to prevent
// double submission or interruption
$('#cancel-btn').addClass('disabled');
$(this).addClass('disabled');
// trigger the AJAX require to process the uploaded file on the server side
$.post($('#form').attr('action'), $('#form').serialize());
// redirect the user to view list
// this being called after a short delay to "try"
// to get the form ajax call sent, but not "wait" for the server response
setTimeout(function() {
window.location.replace( www_root + 'Home/index' );
}, 500);
});
Also, note that I've added an e.preventDefault() and added the e argument to the event handler to make sure the form is not posted by default, only by your ajax code.
And, the timeout time is set here to 500ms. What you need is enough time for the TCP infrastructure in the host computer to send all your form data before you start the redirect. I see a mention of a "file upload" in your comments. If this form is actually uploading a file, that could take way, way longer than 500ms. If it's just sending a few form fields, that should go pretty quickly assuming there are no connection hiccups.
Caveat: Doing it this way is not the 100% reliable way of getting data to your server. There can easily be some conditions where it takes longer than usual just to do a DNS lookup before connecting with your server or your server could momentarily take longer to respond to the initial connection before data can be sent to it. The only 100% reliable way is to wait until the ajax call has succeeded as mentioned elsewhere.
You could perhaps have the best of both worlds (reliability + fast response) if you changed the way your server processes the ajax call so that as soon as it has received the data, it returns a successful response (e.g. in milliseconds after receiving the data) and then after it has sent back the successful response so the browser can then reliably do its redirect, it takes it's 2-3 minutes to actually process the data. Remember, you don't gave to wait until you are done processing the request to return a response. Then, you know that the server has received the data, but the browser doesn't have to wait for the processing time. If you don't always want this ajax call to work that way, you can pass an argument to the ajax call to instruct the server whether you want the fast response or not.
Why not try this:
$.ajax({
url: $('#form').attr('action'),
type: 'post',
data: $('#form').serialize(),
success: function() {window.location.replace( www_root + 'Home/index' );}
});

Links within refreshing div not working

I'm following the example below to continuously refresh a div with a mysql table.
http://techoctave.com/c7/posts/60-simple-long-polling-example-with-javascript-and-jquery
I'm using the complete and timeout parameter of ajax to refresh the div instead of using setinterval and settimeout.
The problem I'm having is that the returning data can include links and these are not working when clicked. I believe the problem could be that the div is constantly refreshing and thus I the click is ignored. How do you allow links within a refreshing div? It works with setinveral and settimeout but I want to use long polling to allow real time updates.
Here is my code.
// get page url variables
function getUrlVars() {
var vars = {};
var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) {
vars[key] = value;
});
return vars;
}
// set var for parent id to scroll to
var tid = getUrlVars()["tid"];
var pid = getUrlVars()["pid"];
(function poll(){
// get latest page
$.ajax({
url: "ajax.tickets_details.php?tid=" + tid,
type: 'GET',
cache: false,
success: function(html) {
// print results from get in div
$("#ticket_updates").html( html );
},
complete: poll,
timeout: 30000
});
})();
Thanks!
I've just read that tutorial and it's based on false information.
this tutorial says:
This means our poll function won't get called again until both the
ajax call is complete and (at-least) thirty (30) seconds have passed.
this isn't true. If your request returns in < 30s it will fire again immediately, thus causing your problem. The Actual definition of timeout is:
Set a timeout (in milliseconds) for the request. This will override
any global timeout set with $.ajaxSetup(). The timeout period starts
at the point the $.ajax call is made; if several other requests are in
progress and the browser has no connections available, it is possible
for a request to time out before it can be sent. In jQuery 1.4.x and
below, the XMLHttpRequest object will be in an invalid state if the
request times out; accessing any object members may throw an
exception. In Firefox 3.0+ only, script and JSONP requests cannot be
cancelled by a timeout; the script will run even if it arrives after
the timeout period.
So this means if the request takes more than 30s it will cancel the waiting handler only (not the call itself, this will continue but the javascript handler will go out of scope).
There is even a comment highlighting this flaw:
I'd find a new tutorial as that one appears to be talking nonesense. This technique is not doing "server push" at all. Only web sockets can push from the server. HTTP 1.1 does not support any server push methods at all.

JSON Parsing Weirdness - Broken or Just Slow?

In jQuery, parsing a bunch of points to draw on a HTML5 canvas. Encountered a strange bug -- but my knowledge of this area is pretty limited so perhaps there's a good explanation.
This works every time:
var json = $.getJSON( "../models/" + id + ".json");
alert("fjkld");
paths = JSON.parse(json.responseText);
This fails every time:
var json = $.getJSON( "../models/" + id + ".json");
paths = JSON.parse(json.responseText);
Anyone have any idea why? Is it because the alert pauses something while the parser 'catches up'? That doesn't make intuitive sense to me but it's the only explanation.
Actually I know this is correct because if I hit "OK" on the alert really fast it fails again.
Can someone please explain to me why this is happening?
getJSON is asynchronous. This means that it returns immediately, before the XMLHTTPRequest has completed. Because alert is a blocking function, all code is halted until you press OK. If you take a while, the request has completed, so responseText is available; if alert isn't present, or you press OK very quickly, the HTTP request has not completed, so the text has not completed.
You need to use a callback function instead: this is a function that will be executed when the AJAX request is complete:
$.getJSON( "../models/" + id + ".json", function(paths) {
// access paths here
});
See the documentation for $.getJSON.
This happens because the getJSON call is asynchronous. Once the call to getJSON is complete all you know is that the browser has kicked off the request for the file. You do not know if the request has been completed or not. Sure, the call to the alert function gives the browser enough time (usually) to get the full file, but as you discovered sometimes that's not true.
Far better is to supply a callback that will be called once the file has been downloaded:
$.getJSON(fileName, function(data) {
paths = JSON.parse(data);
..do something with paths..
});
Although note that paths won't be available until the callback executes.
You need to set up a callback function in the getJSON call to ensure that the response has had time to complete. In the flow of the ajax call the function that generates the getJSON call continues while the getJSON happens. There is no guarantee that the json request has completed when teh JSON.parse() is being called. The proper syntax for the call is :
jQuery.getJSON( "../models/" + id + ".json", function(data, status, xhr){ JSON.parse(data);} )
Check out the api for the getJson call here: http://api.jquery.com/jQuery.getJSON/
Put your logic inside the callback.
$.getJson("../models/" + id + ".json", function(response) {
paths = JSON.pars(response.responseText);
});
Or something like that. As a request API call is an asynchronous call, you have to wait for the server response before you can move forward. That's where callbacks come in. They're called by the asynchronous API when the request is complete. They usually also have success status flags to tell you if your request was successful.
http://api.jquery.com/jQuery.getJSON/

Categories