Is there a way I can make a progress bar for ajax using jquery using post data (QUERIES) and not uploading a file?
Because the ProgressEvent.lengthComputable read-only property is a Boolean flag indicating if the resource concerned by the ProgressEvent has a length that can be calculated.
If not, the ProgressEvent.total property has no significant value. So my problem is I use ajax for long process queries and not for uploading file. Thanks.
Hi from what i understand, you have a long process running on server that you call using XHR, now you want to show a progress bar in the browser.
Short answer
Not possible in ajax
Long answer
Ajax is just same as http request and there is no way to know the status of the request on server . Only the final output and http status code is available.
Solution
What you want is web sockets and not ajax. WS are bi directional communication standards. On server you can keep publishing the status of the request into the web socket. On client side read from web socket and display the changes.
So overall you need a WS server. Send request from client using websocket and finally keep reading websocket for status till you get the results.
Is this complication needed
Although this is very long and tedious job i know that some projects need it if they have long tasks. Another alternative that you can have is push the task into celery and use XHR poling to get the status of the job.
Hope this helps
In an AJAX request you do not know the response duration on the time you execute the call.
A solution might be to set a timeout limit for the ajax call and animate a progress bar depending on this time. Of course the response will be available before this time limit (at least that's what we want). In this case, force the progress bar to complete it's animation and proceed with your data manipulation.
EXAMPLE
HTML
<!-- LOADER -->
<div id="loader"></div>
jQuery
/**
* Execute ajax request and initialize loader animation
* #param time {number} The ajax timeout limit and progress bar animation duration
*/
function executeAjax(time) {
// Start progress bar initialization
$('#loader').animate({ 'width', '100%' }, time);
// Execute ajax call
$.ajax({
url: '...',
method: 'POST',
data: { ... },
dataType: 'json',
success: function(data) {
// Stop previous animation and start a new one with 0.5 sec duration
$('#loader').stop().animate({ 'width', '100%' }, 500)
.queue(function() {
// Handle the response data here
$(this).dequeue();
});
},
error: function(jqXHR, errorType) {
alert('Error: ' + errorType);
},
timeout: time
});
}
// Call the function passing a timeout of 10 seconds
executeAjax(10000);
Related
I know we can make a javascript ajax request from some server and it either receives the response or gives timeout error after some time.
Let's consider this scenario when we don't want to wait for the request rather the server would send a response(or we can say it would be another request from server to client) async at any time after getting the request and then call a javascript CB function with the response.
I am looking for ideas for how to go about it mainly supporting all modern browsers and if possible not relying on any 3rd party plugin except may be jQuery.
The main feature of Ajax is that it IS asynchronous by default, and your program will continue to run without waiting for the response. So unless I'm misreading your question, it is what you need.
If you use jquery, then you pass in a callback function that will execute only when the server sends back a response. You can specify a timeout in the settings, though I'm not sure what the maximum time you can provide without getting a timeout error. But it will be several seconds, at least.
You can even specify different callbacks for success and fail as follows (adapted from the jquery ajax API, but added a timeout of 5 seconds):
var request = $.ajax({
url: "http://www.some.url/",
method: "GET",
data: { some : stuff },
dataType: "html",
timeout: 5000
});
request.done(function( data ) {
console.log( "SUCCESS: " + data );
});
request.fail(function() {
console.log( "Request failed");
});
I came across this question after 4 years. I dont remember in what context I asked this but for anyone who has the same query:
Http is a request/response protocol. Which means the client sends a request and the server responds to that request with some message/data. Thats the end of the story for that request.
In order for the server to trigger something on the clientside we will have to use something that keeps the connection to the server rather than ending the communication after getting the response. Socket.io is bi directional event driven library that solves this problem.
To update a cart (PHP Session storage and reserve the stock of items in database) on my online shop, I simply add a timeout of 100ms after calling it and remove Success/Error callback.
$.ajax({
url: 'http://www.some.url/',
method: 'GET',
data: {
some : 'stuff'
},
dataType: 'html',
timeout: 100
});
Note : It doesn't matter if some requests didn't arrive, because when the order is saved, an update of the whole cart is sent with a callback.
If your query needs acknowledge, don't use that solution !
I believe your question is similar to this
by Paul Tomblin. I use the answer provided by gdoron, which is also marked as the best solution, and also the comment by AS7K.
$.ajax({
url: "theURL",
data: theData
});
NB: No async parameter provided.
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>
I have the following query in jquery. It is reading the "publish" address of an Nginx subscribe/publish pair set up using Nginx's long polling module.
function requestNextBroadcast() {
// never stops - every reply triggers next.
// and silent errors restart via long timeout.
getxhr = $.ajax({
url: "/activity",
// dataType: 'json',
data: "id="+channel,
timeout: 46000, // must be longer than max heartbeat to only trigger after silent error.
error: function(jqXHR, textStatus, errorThrown) {
alert("Background failed "+textStatus); // should never happen
getxhr.abort();
requestNextBroadcast(); // try again
},
success: function(reply, textStatus, jqXHR) {
handleRequest(reply); // this is the normal result.
requestNextBroadcast();
}
});
}
The code is part of a chat room. Every message sent is replied to with a null rply (with 200/OK) reply, but the data is published. This is the code to read the subscribe address as the data comes back.
Using a timeout all people in the chatroom are sending a simple message every 30 to 40 seconds, even if they don't type anything, so there is pleanty of data for this code to read - at least 2 and possibly more messages per 40 seconds.
The code is 100% rock solid in EI and Firefox. But one read in about 5 fails in Chrome.
When Chrome fails it is with the 46 seconds timeout.
The log shows one /activity network request outstanding at any one time.
I've been crawling over this code for 3 days now, trying various idea. And every time IE and Firefox work fine and Chrome fails.
One suggestion I have seen is to make the call syncronous - but that is clearly impossible because it would lock up te user interface for too long.
Edit - I have a partial solution: The code is now this
function requestNextBroadcast() {
// never stops - every reply triggers next.
// and silent errors restart via long timeout.
getxhr = jQuery.ajax({
url: "/activity",
// dataType: 'json',
data: "id="+channel,
timeout: <?php echo $delay; ?>,
error: function(jqXHR, textStatus, errorThrown) {
window.status="GET error "+textStatus;
setTimeout(requestNextBroadcast,20); // try again
},
success: function(reply, textStatus, jqXHR) {
handleRequest(reply); // this is the normal result.
setTimeout(requestNextBroadcast,20);
}
});
}
Result is sometimes the reply is delayed until the $delay (15000) happens, Then the queued messages arrive too quicly to follow. I have been unable to make it drop messages (only tested with netwrok optomisation off) with this new arrangement.
I very much doubt that delays are dur to networking problems - all machines are VMs within my one real machine, and there are no other users of my local LAN.
Edit 2 (Friday 2:30 BST) - Changed the code to use promises - and the POST of actions started to show the same symptoms, but the receive side started to work fine! (????!!!???).
This is the POST routine - it is handling a sequence of requests, to ensure only one at a time is outstanding.
function issuePostNow() {
// reset heartbeat to dropout to send setTyping(false) in 30 to 40 seconds.
clearTimeout(dropoutat);
dropoutat = setTimeout(function() {sendTyping(false);},
30000 + 10000*Math.random());
// and do send
var url = "handlechat.php?";
if (postQueue.length > 0) {
postData = postQueue[0];
var postxhr = jQuery.ajax({
type: 'POST',
url: url,
data: postData,
timeout: 5000
})
postxhr.done(function(txt){
postQueue.shift(); // remove this task
if ((txt != null) && (txt.length > 0)) {
alert("Error: unexpected post reply of: "+txt)
}
issuePostNow();
});
postxhr.fail(function(){
alert(window.status="POST error "+postxhr.statusText);
issuePostNow();
});
}
}
About one action in 8 the call to handlechat.php will timeout and the alert appears. Once the alert has been OKed, all queued up messages arrive.
And I also noticed that the handlechat call was stalled before it wrote the message that others would see. I'm wondering if it could be some strange handling of session data by php. I know it carefully queues up calls so that session data is not corrupted, so I have been careful to use different browsers or different machines. There are only 2 php worker threads however php is NOT used in the handling of /activity or in the serving of static content.
I have also thought it might be a shortage of nginx workers or php processors, so I have raised those. It is now more difficult to get things to fail - but still possible. My guess is the /activity call now fails one in 30 times, and does not drop messages at all.
And thanks guys for your input.
Summary of findings.
1) It is a bug in Chrome that has been in the code for a while.
2) With luck the bug can be made to appear as a POST that is not sent, and, when it times out it leaves Chrome in such a state that a repeat POST will succeed.
3) The variable used to store the return from $.ajax() can be local or global. The new (promises) and the old format calls both trigger the bug.
4) I have not found a work around or way to avoid the bug.
Ian
I had a very similar issue with Chrome. I am making an Ajax call in order to get the time from a server every second. Obviously the Ajax call must be asynchronous because it will freeze up the interface on a timeout if it's not. But once one of the Ajax calls is a failure, each subsequent one is as well. I first tried setting a timeout to be 100ms and that worked well in IE and FF, but not in Chrome. My best solution was setting the type to POST and that solved the bug with chrome for me:
setInterval(function(){
$.ajax({
url: 'getTime.php',
type: 'POST',
async: true,
timeout: 100,
success: function() { console.log("success"); },
error: function() { console.log("error"); }
});
}, 1000);
Update:
I believe the actual underlying problem here is Chrome's way of caching. It seems that when one request fails, that failure is cached, and therefore subsequent requests are never made because Chrome will get the cached failure before initiating subsequent requests. This can be seen if you go to Chrome's developer tools and go to the Network tab and examine each request being made. Before a failure, ajax requests to getTime.php are made every second, but after 1 failure, subsequent requests are never initiated. Therefore, the following solution worked for me:
setInterval(function(){
$.ajax({
url: 'getTime.php',
cache: false,
async: true,
timeout: 100,
success: function() { console.log("success"); },
error: function() { console.log("error"); }
});
}, 1000);
The change here, is I am disabling caching to this Ajax query, but in order to do so, the type option must be either GET or HEAD, that's why I removed 'type: 'POST'' (GET is default).
try moving your polling function into a webworker to prevent freezing up in chrome.
Otherwise you could try using athe ajax .done() of the jquery object. that one always works for me in chrome.
I feel like getxhr should be prefixed with "var". Don't you want a completely separate & new request each time rather than overwriting the old one in the middle of success/failure handling? Could explain why the behavior "improves" when you add the setTimeout. I could also be missing something ;)
Comments won't format code, so reposting as a 2nd answer:
I think Michael Dibbets is on to something with $.ajax.done -- the Deferred pattern pushes processing to the next turn of the event loop, which I think is the behavior that's needed here. see: http://www.bitstorm.org/weblog/2012-1/Deferred_and_promise_in_jQuery.html or http://joseoncode.com/2011/09/26/a-walkthrough-jquery-deferred-and-promise/
I'd try something like:
function requestNextBroadcast() {
// never stops - every reply triggers next.
// and silent errors restart via long timeout.
getxhr = jQuery.ajax({
url: "/activity",
// dataType: 'json',
data: "id="+channel,
timeout: <?php echo $delay; ?>
});
getxhr.done(function(reply){
handleRequest(reply);
});
getxhr.fail(function(e){
window.status="GET error " + e;
});
getxhr.always(function(){
requestNextBroadcast();
});
Note: I'm having a hard time finding documentation on the callback arguments for Promise.done & Promise.fail :(
Perhaps it can be worked around by changing the push module settings (there are a few) - Could you please post these?
From the top of my head:
setting it to interval poll, would kinda uglily solve it
the concurrency settings might have some effect
message storage might be used to avoid missing data
I would also use something like Charles to see what exactly does happen on the network/application layers
Is there a way to specify maximum execution time of an ajax post to the server so if the server doesn't respond, then keep trying for 10 seconds and then continue with the rest of the code??
Function doajaxPost(){
var returned_value="";
// #############I NEED THIS CODE TO TRY TO POST THE DATA TO THE SERVER AND KEEP
// #############TRYING FOR 10 SECONDS AND THEN CONTINUE WITH THE REST OF THE CODE.
jQuery.ajax({
url: 'ajaxhandler.php',
success: function (result) {
returned_value=result;
},
async: false
});
// ###################################################
alert(returned_value);
some other code
.
.
.
}
Use timeout:
jQuery.ajax({
url: 'ajaxhandler.php',
success: function (result) {
returned_value=result;
},
timeout: 10000,
async: false
});
However, alert(returned_value); will execute just after your call (won't wait for the call to finish).
The JQuery API documentation tells how to set a "timeout".
http://api.jquery.com/jQuery.ajax/
While other answers here are correct, learning to check the documentation for yourself is more valuable than knowing just this answer.
You can set timeout value for your ajax request.
timeout
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.
Here is an example:
$.ajax({
url: "ajaxhandler.php",
...
timeout: 10000,
...
});
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.
Hopefully, this will help others like me who aren't completely fluent in JavaScript or, more to the point, aren't completely fluent in reading jQuery documentation.
I admit, I looked at the jQuery.Ajax docs, and easily enough found the section that talks about setting a timeout:
timeout
Type: Number
Set a timeout (in milliseconds) for the request. A value of 0 means there will be no timeout. 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.
But lacking an example, I was still clueless how to specify the timeout value. The secret sauce is at the top of the article, where it says:
In JavaScript, this translates to this sort of syntax:
$.ajax({
url: "https://example.com/my-endpoint",
...
timeout: 0,
...
});
In the above example (which specifies a timeout of 0 to disable timeouts for this request), each key/value pair (as mentioned in the documentation) appears in the code as [key]: [value]
I like to create a progress bar for my ajax calls.
For this I can make my server side script to return the state of it's progress.
So I need for javascript to read this progress level and show it.
Is it possible or am I on the wrong road?
You could try something like this (some pseudocode, assuming jQuery, since you've tagged the question as such):
var poll;
$.ajax({
url: 'your_ajax_script',
beforeSend: function(){ // set up out-of-band status polling
poll = setInterval( function(){
$.get('your_script_that_returns_status',
function(data){
update_progressbar(data);
});
}, 1000 ); // update every second?
},
success: function(data) {
clearInterval( poll ); // stop polling
finalize_or_hide_progressbar(); // clean up
do_something_with( data ); // your "done" logic
}
});
Either poll at intervals, returning the payload on the final successful call, or run two AJAX calls - the first retrieving the actual data, and the second polling for update percentage.