I have an issue when trying to get Javascript to execute functions in my desired order. I'm trying to get a jQuery modal form to load information based on a certain selection. I have two SELECT boxes that need to be loaded, but the contents of the second SELECT box depend entirely on the selected value of the first SELECT box.
I made the following functions to request the information I need:
function get_Subjects(varID, callback){
$.post("../vars/get_SID.php", { vid : varID },
function(result){
getInfo('tbsubjectdiv', '../vars/findSubjectlist.php?sid='+result);
});
callback();
}
function get_Selectedfields(varID, callback){
$.post("../vars/requestTblock.php", { vid : varID },
function(result){
populateForm('tbWiz', result);
document.form_tbWiz.varname.disabled = true;
$('.trSearch').hide();
$('.trValueset').hide();
});
callback();
}
function get_TextblockType(varID, callback){
$.post("../vars/requestVtype.php", { vid : varID },
function(result){
if(result == 0){ //Opzoeken
$('.trSearch').show();
}else if(result == 1){ //Datum vergelijken
$('.trSearch').show();
$('.trValueset').show();
}else if(result == 2){ //Percentage
//
}
});
callback();
}
The first function checks the MySQL database for the selected value of the FIRST SELECT field, and loads the results into the second SELECT field.
The second function requests the rest of the rest of the form data, and populates the form using populateForm(). It also hides certain parts of my form in preparation for function three.
The third function basically requests which parts of the form have to be displayed, because that's not always the same.
The whole idea behind this is that I want to use populateForm() to populate all of the form fields. In order for populateForm() to properly set the selected SELECT option, the particular SELECT field must first contain the OPTION it needs to select. Makes sense. I try to make sure of this with my first function, which will load all of the OPTIONs. THEN I try to use the get_Selectedfields() to populate all the proper values. This is not what happens though. No matter what I try to do, getInfo() in the first function is ALWAYS being called LAST. This makes it impossible for populateForm() to select the proper option, which is driving me mad.
I'm trying to "force" the execution-order by doing this:
function getTextblock(var_ID){
get_Subjects(var_ID, function() {
get_Selectedfields(var_ID, function() {
get_Textblocktype(var_ID, function() {
// Done
});
});
});
}
When I realised it still did not work the way I wanted, I decided to use Chrome's Developer Tools to check the order in which everything is executed. It all works as expected, but at the very end it jumps straight back to getInfo(), which is part of the FIRST function I called. I'm absolutely clueless as to why getInfo() gets executed last. If this just gets executed at the very beginning, where I want it to execute, it would all work fine.
You have to call the callback in the callback function of the post request:
function get_Subjects(varID, callback){
$.post("../vars/get_SID.php", { vid : varID },
function(result){
getInfo('tbsubjectdiv', '../vars/findSubjectlist.php?sid='+result);
callback();
});
}
function get_Selectedfields(varID, callback){
$.post("../vars/requestTblock.php", { vid : varID },
function(result){
populateForm('tbWiz', result);
document.form_tbWiz.varname.disabled = true;
$('.trSearch').hide();
$('.trValueset').hide();
callback();
});
}
function get_TextblockType(varID, callback){
$.post("../vars/requestVtype.php", { vid : varID },
function(result){
if(result == 0){ //Opzoeken
$('.trSearch').show();
}else if(result == 1){ //Datum vergelijken
$('.trSearch').show();
$('.trValueset').show();
}else if(result == 2){ //Percentage
//
}
callback();
});
}
The POST is being handled asynchronously in your functions so your "callback" is really just being executed almost immediately after your initial call, whereas the callback of $.post
is being executed after the post has occurred. Does that help you sort things out? You will probably need to kick off the rest of the process in the callback of $.post("../vars/get_SID.php", { vid : varID }...
$.post
is shorthand for $.ajax
so you can read up a bit more in the jQuery docs, but I would not suggest switching to synchronous requests. If you absolutely must have one request finished before the next can execute then kicking off that next step from the callback is the way to go.
You're using ajax. The first a is for asynchronous. If you called the functions from the function(result) blocks then they would occur in order.
Alternatively (and this isn't a great idea but you can do it) use the $.ajax() object and set async to false.
As you don't know how long long an ajax request will actually take, you can only chain events within the ajax response:
function getTextblock(var_ID){
$.post(YOUR_TARGET, YOUR_DATA, function(result){
YOUR_CODE
// CHAIN HERE, call new function or sub ajax request
});
}
Wesley,
The javascript will execute always on the predefined order. If you put a bunch of "alerts()" in the middle of your code, you can taste that.
But this is not true for callbacks, because they will be moved to the bottom of execution stack on javascript where we can't determine the order, since they are called by a AJAX return which by definition is asynchronous.
Even though your ajax executes in a millisecond, the callback will not be executed until all methods in your script block have finished.
You have, actually three options:
// The data you need first function myStartPoint() { $.post(url, function(result) { // do what you need with this result (this is your callback, but anonymous) // then, call the next step secondPoint(); }); } function secondPoint() { $.post(url, function(result) { // again, the callback is anonymous... your hardly need to declare something named callback // chain how many points as you need nextPoint(); } }