问题
I'm just testing a local application and wanted to make something like this:
- Click button, that's easy.
- Perform AJAX request and create a database table.
- Once the table is created, perform another series of AJAX requests and populate the table according to some parameters gotten from a series of select boxes.
- "Animate" the whole thing using a progress bar.
Surprisingly, everything is working fine (apart the last point), but I'm getting some troubles.
The table gets created and populated but, for some reasons, the very last AJAX requests doesn't fire correctly, since it's not passing a parameter correctly.
My ajax requests are ALL asyncronous, if I set them syncronous the whole thing will freeze, but all the requests are executed correctly, even the very last one.
For instance, let's say that I don't want to use asyncronous requests in order to DON'T freeze the page and be able to show a progress bar.
The questions are the following:
- Is it possible to call the same script twice?
- Is there an efficient way to avoid ajax requests executing before other ajax requests?
After reading a whole bunch of topics here in stackoverflow, I edited my code and tried to:
- use jQuery.AJAX prototype instead of jQuery.POST
- Set everything asyncronously, in order to don't freeze the page and be able to handle a progress bar
- perform the very next AJAX request into the "success" callback of the parent AJAX request.
At this point, I still have another question:
By stacking AJAX requests, is it actually TRUE that everything executed into the "success" callback will be executed AFTER the ajax requests has completed?
This is what I'm performing:
$.ajax({
type: "POST",
url: '../libs/php libraries/agenda.php',
data: {'action':'create>agenda', 'sqlname': createInfo},
processData: true,
dataType: "json",
timeout: 60000,
async: true,
success: function(res) {
$('#popup_content').append(res.log);
var dateList = new Array();
var dateObj = new Date();
var m = dateObj.getMonth();
var Y = dateObj.getFullYear();
for (var i = 1; i <= 31; i++) {
dateList.push(i+"/"+m+"/"+Y);
}
for (var i = 0; i < dateList.length; i++) {
var rs = false;
$.ajax({
type: 'POST',
url: '../libs/php libraries/agenda.php',
data: {'action':'validate>date', 'date': dateList[i]},
processData: true,
timeout: 60000,
async: true,
dataType: "json",
success: function(x) {
$('#popup_content').append(x.log);
if (x.res == 'true') {
rs = dateList[i];
}
if (rs != false) {
$.ajax({
type: 'POST',
url: '../libs/php libraries/agenda.php',
data: {'action':'create>day', 'date': rs, 'sqltable': createInfo},
processData: true,
timeout: 60000,
async: true,
dataType: "json",
success: function(newResult) {
console.log(newResult.res);
$('#popup_content').append(newResult.log);
}
});
}
}
});
}
}
});
the first AJAX request executes correctly, the second one does too, but in the third one (the one with data: {'action':'create>day', 'date': rs, 'sqltable': createInfo}) is getting fired but is missing the parameter rs defined above.
Also, to be clearer, rs is a temporary variable I've defined when I was trying to make the requests outside the "success" callback and when using $.when and $.done, in this case the variable rs is useless, but It won't change anything.
Again, as said above, the whole thing works using a syncronous request, but doesn't by using an asyncronous one.
Moreover, I'm just going to use this script locally, so delays or every problematic related to delays caused by servers and client are not important.
Is there any reason for the last request to don't work with an asyncronous request? if so is there a valuable solution for this case? I've also checked the topics about the queue, but it didn't solve my problem either. For some reasons, asyncronously, the last AJAX requests get just partially fired, since the variable rs is not getting passed correctly.
回答1:
One solution is to use queue() function. This way you can execute as many functions as you want
var ajaxQueue = $({});
$.ajaxQueue = function(date, ajaxOpts) {
// queue the method. a second call wont execute until this dequeues
ajaxQueue.queue(function(next) {
// for this example I serialize params, but you can save them in several variables
// and concat into ajaxOpts.data
var params = method_that_get_params_and_serialize_them();
ajaxOpts.data = params;
ajaxOpts.complete = function() {
next();
};
$.ajax(ajaxOpts);
});
};
Then your functions have no need of shared vars, with the concurrency conflicts that it causes.
It should be like this:
$.ajax({
type: "POST",
url: '../libs/php libraries/agenda.php',
data: {'action':'create>agenda', 'sqlname': createInfo},
processData: true,
dataType: "json",
timeout: 60000,
async: true,
success: function(res) {
$('#popup_content').append(res.log);
var dateList = new Array();
var dateObj = new Date();
var m = dateObj.getMonth();
var Y = dateObj.getFullYear();
for (var i = 1; i <= 31; i++) {
dateList.push(i+"/"+m+"/"+Y);
}
for (var i = 0; i < dateList.length; i++) {
processDate(dateList[i]);
}
}
});
function processDate(date){
$.ajaxQueue({
type: 'POST',
url: '../libs/php libraries/agenda.php',
data: {'action':'validate>date', 'date': date},
processData: true,
timeout: 60000,
async: true,
dataType: "json",
success: function(x) {
$('#popup_content').append(x.log);
if (x.res == 'true') {
$.ajax({
type: 'POST',
url: '../libs/php libraries/agenda.php',
data: {'action':'create>day', 'date': date, 'sqltable': createInfo},
processData: true,
timeout: 60000,
async: true,
dataType: "json",
success: function(newResult) {
console.log(newResult.res);
$('#popup_content').append(newResult.log);
}
});
}
}
});
};
}
来源:https://stackoverflow.com/questions/24821064/stacking-multiple-ajax-requests-on-success-jquery