To upload multiple files, I am using JavaScript to loop through the files.
To upload the files I am using the jQuery form plugin http://archive.plugins.jquery.com/project/form
Now, when the loop runs through, it runs to the end of the loop instantly, and uploads all files in one go.
Is there a way to get the loop to hold off during each upload?
This is an example of the loop im using (the actual code is quite large)
for(i=0;i<=num;i++)
{
if(go1){
<?php //if 1 upload only, hide add and upload button ?>
$('#ad,#ok').hide();
var z=i;
$('#up'+i).ajaxSubmit({
dataType:"json",
beforeSubmit:function(before){
$('#loadingsignup').show;
$("#resultsignup").empty().hide();
},
success:function(retour){
res=retour;
if(num<1){ <?php // only one upload, redirect if uploaded correct, reintroduce upload button if error ?>
if(res.ok=="ok"){
window.location.replace('<?php echo $config['baseurl']; ?>/player/'+res.aid);
}else{
$('#rs'+z).append('<div class="pasgood">'+res.err+'</div>').show();
$('#ad,#ok').show();
}
}
}
});
}
}
I really need the loop to move through the uploads one at a time.
No, the loop is synchronous while the upload is asynchronous. If you want the uploads to happen one after the other, you will need to fire the second one from the success callback of the first one etc.
function upload(i, suc, err) {
if (i > num)
return suc();
$('#up'+i).ajaxSubmit({
dataType:"json",
beforeSubmit:function(before){
$('#loadingsignup').show();
$("#resultsignup").empty().hide();
},
success:function(res){
if(res.ok=="ok"){
$('#ad,#ok').show();
upload(i+1, suc, err); // next one
} else {
$('#rs'+i).append('<div class="pasgood">'+res.err+'</div>').show();
err(res.err); // or continue with the rest?
}
},
error: err
});
}
upload(0, function allDone(){
window.location.replace('<?php echo $config['baseurl']; ?>/player/');
}, function somethingWrong(){ … });
Use async: false as $.ajax() param. This will avoid sending files at once, $.ajax will wait until execution of the request complete, thean the cycle will continue to the next item.
DOCS:
By default, all requests are sent asynchronously (i.e. this is set to true by default). If you need synchronous requests, set this option to false. Cross-domain requests and dataType: "jsonp" requests do not support synchronous operation. Note that synchronous requests may temporarily lock the browser, disabling any actions while the request is active. As of jQuery 1.8, the use of async: false with jqXHR ($.Deferred) is deprecated; you must use the complete/success/error callbacks.
But anyway you need an syncronious execution.
Related
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>
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' );}
});
How can I make sure that a piece of code has executed completely before executing another? I am sending some ajax requests to a server and then using the returned data to generate the rest of the webpage. the things is, is that i need to have all that data in the webpage to proceed with the rest of the code as that code will affect what has been generated and, that code, runs before the json requests and all of that have finished... is there any way I can make sure this does not happen? I managed to solve it by performing the requests and then asking the user to press a button but that is a total no-sense way of doing it.
Any ideas?
Here is some code: The problem is that the second line is executed before the first (there are many calls to similar JSON functions).
$.getJSON(url, function(data){ $("#mycontent").append("..... stuff here...... create loads of dibs with class set to mydivclass"); });
...
$("div.mydivclass").hide();
Unforunately I cannot use the ajax synchronous property because: "dataType: "jsonp" requests do not support synchronous operations"
If you are using jQuery 1.5+ you can make use of deferreds to solve your issue:
function first_ajax_request() {
return jQuery.ajax(
// Your settings here
success: success_function_1
);
}
function second_ajax_request() {
return jQuery.ajax(
// Your settings here
success: success_function_2
);
}
function final_sucess_callback() {
// Do all your display work.
}
jQuery.when(first_ajax_request(),
second_ajax_request()).then(final_success_callback);
There is an excellent article on the topic that you should read up on as well by Eric Hynds. He gives some examples of exactly the kind of problem you are trying to solve.
jquery requests are asynchonize by default , so your code does not wait for the response , so you have no guarantee that code after request will execute after the response , so you can set the request synchronize by set the async property false , now the request is synchronize and you can gurantee the rest of the code will execute after the response from the server ,
like this .
$.ajax({
url: "page.php",
processData: false,
data: xmlDocument,,
async:false,
success: handleResponse
});
I'm making a mailing list script that takes advantage of ajax (async=false) to send emails in chunks.
Basically the cycle is this:
var i = 0;
for(i;i<num_rows;i=i+mxt){
if($("#panic").val()=='1'){
break;
}
perc = (i*100)/num_rows;
startThread(i,perc);
}
Tha panic value is set by a button, the problem is that during the cycle (that works) I can't interact with the page.
What am I doing wrong?
Thank you
EDIT:
function startThread(i,perc){
l_a = i;
l_b = mxt;
headers = '&mail_from='+mail_from+'&mail_from_name='+mail_from_name+'&mail_subject='+mail_subject;
$.ajax({
type: "POST", url: "ajax/thread.php", data: "l_a="+l_a+"&l_b="+l_b+headers,
success: function(html){ $("#progressbar").progressbar({value: perc}); },
async: false
});
}
Your startThread() function name is misleading, because JavaScript in web browsers in not only single threaded, but it shares the same thread with the page rendering.
Since you're using async=false, the $.ajax call become a blocking function, and this blocks the page rendering thread, making the UI unresponsive.
Quoting the jQuery documentation (emphasis added):
async
Default: true
By default, all requests are sent asynchronous (i.e. this is set to true by default). If you need synchronous requests, set this option to false. Cross-domain requests and dataType: "jsonp" requests do not support synchronous operation. Note that synchronous requests may temporarily lock the browser, disabling any actions while the request is active.
Possible solutions:
Piggyback your data in one JSON object, and send just one $.ajax request. If possible use async=true.
I find myself having to get around waiting for AJAX in jQuery often these days. Problem is, I have to do loops and crap to wait for them. What are some ways that I can wait for the AJAX event to finish before executing code (preferably without making extra functions)?
Generally, if there is a chance that a repeating AJAX request may not be finished before it is called again, I use a flag to prevent overlapping requests.
First, define the flag and set it initially as false. Whenever you are sending your AJAX request, check to see if this flag is false. If it is, then proceed with the request - not before setting the flag to true mind. Once the AJAX request has completed, set the flag back to false.
Using the above method, only one instance of the AJAX query will run at once. I'm sure jQuery must have a way of seeing if there is an AJAX request being processed already or not, but I'm a MooTools man.
What method are you using to make AJAX calls? If you use the built in $.ajax(), you can set the success property to a callback function which will be called once the AJAX request returns successfully. There is also the complete callback which will always be called whether it succeeds or fails.
From the jQuery API:
$.ajax({
type: "POST",
url: "some.php",
data: "name=John&location=Boston",
success: function(msg){
alert( "Data Saved: " + msg );
}
});
There is also a complete option that you can use.
http://api.jquery.com/jQuery.ajax/