Reputation: 137
I have a for loop where I am calling three functions. I need the functions to run in sequence only after the previous one has completed.
I have tried to achieve this using callbacks but it doesn't seem to be working.
Here's the code:
for(let i=0;i<boxval.length;i++){
var value=boxval[i];
a(value,function(returnedValue){
b(returnedValue,function(returnedValue){
c(returnedValue,function(returnedValue){
d();
});
});
});
}
function a(val, callback){
$
.ajax({
type : "get",
url : "myservlet",
beforeSend : function() {
$(
'#text1')
.css(
{
"color" : "red"
});
$(
'#text1')
.text(
"Running Graph");
},
data : {
"boxval" : val
},
success : function(
responseText) {
$(
'#text1')
.css(
{
"color" : "green"
});
$(
'#text1')
.text(
responseText);
callback(val);
}
});
}
function b(val, callback){
$
.ajax({
type : "get",
url : "ConnectServlet",
beforeSend : function() {
$(
'#text2')
.css(
{
"color" : "red"
});
$(
'#text2')
.text(
"Copying Files and preparing pSet");
},
data : {
"boxval" : val
},
success : function(
responseText) {
$(
'#text2')
.css(
{
"color" : "green"
});
$(
'#text2')
.text(
responseText);
callback(val);
}
});
}
function c(val, callback){
$
.ajax({
type : "get",
url : "CopyServlet",
beforeSend : function() {
$(
'#text3')
.css(
{
"color" : "red"
});
$(
'#text3')
.text(
"Running Dynamic Diff Graph");
},
data : {
"boxval" : val
},
success : function(
responseText) {
$(
'#text3')
.css(
{
"color" : "green"
});
$(
'#text3')
.text(
responseText);
callback(val);
}
});
}
function d(){
$(
'#summary')
.show();
}
What am I doing wrong and how do I get this to work?
Upvotes: 1
Views: 2084
Reputation: 19007
As many have given you solutions already I wont spare time giving the same solution, I still am sure that the execution will not happen as expected, Since you have callbacks which are assigned values using Index
it will break for sure. Reason is when the ajax is success and the callback is executed the the index will be incremented to point to a different number. Now your callbacks will take these values which is wrong.
So the solution to handle this will be simply to pass back the value passed into the ajax call back into the callback
Change the code as below.
for (i = 0; i < boxval.length; i++) {
a(boxval[i], function (returnedValue) {
b(returnedValue, function (returnedValue) {
c(returnedValue);
});
});
}
And change your callback()
to callback(val)
, val
is what passed into the ajax function.
So the conclusion is to change the for loop
and the callback
as suggested above and move the callback(val)
inside of the success
of ajax.
EDIT: Since you want the functions to execute synchronously you can use Recursive function. That is execute the function from first index unless all the indexs are covered. Here is a sample fiddle (watch console output)
var boxval = [1, 2, 3]
function RecursiveExecution(index) {
var value = boxval[index];
a(value, function(returnedValue) {
b(returnedValue, function(returnedValue) {
c(returnedValue);
if (index < boxval.length -1) { // if there are more items do this process again
RecurrsiveExecution(++index);
}
});
});
}
RecursiveExecution(0); // initiate the recursive function.
Upvotes: 2
Reputation: 3491
Best way to accomplish what you are trying to do is using promise, but if you are not familiar with that(and by your question you are not) it's a bit hard to learn in a few minutes, but I recommend it.
For your code I would have try this:
function a(val, callbackB, callbackC)
{
$.ajax({
type : "get",
url : "myservlet",
beforeSend : function() {
$('#text1').css({"color" : "red"});
$('#text1').text("Running Graph");
},
data : {"boxval" : val},
success : function(responseText) {
$('#text1').css({"color" : "green"});
$('#text1').text(responseText);
callbackB(val,callbackC)
}
});
}
var cbB = function b(val, callback)
{
$.ajax({
type : "get",
url : "ConnectServlet",
beforeSend : function() {
$('#text2').css({"color" : "red"});
$('#text2').text("Copying Files and preparing pSet");
},
data : {"boxval" : val},
success : function(responseText) {
$('#text2').css({"color" : "green"});
$('#text2').text(responseText);
callback(val);
}
});
}
var cbC =function c(val){
$.ajax({
type : "get",
url : "CopyServlet",
beforeSend : function() {
$('#text3').css({"color" : "red"});
$('#text3').text("Running Dynamic Diff Graph");},
data : {"boxval" : val},
success : function(responseText) {
$('#text3').css({"color" : "green"});
$('#text3').text(responseText);
}
});
}
for(i = 0 ; i < boxval.length; i++){
a(boxval[i],cbB,cbC)
});
}
Upvotes: 1
Reputation: 205
For that kind of things i would recommended to use Promises.
but if you don't want to dive in it, i would suggest that you call the next function after getting success.
function a() {
success: function(responseText) {
// code here..
callback();
}
}
function b() {
success: function(responseText) {
// code here..
callback();
}
}
function c() {
success: function(responseText) {
// code here..
callback();
}
}
Upvotes: 0
Reputation: 1089
AJAX is asynchronous call, meaning that it will still be doing it's work and the rest of the javascript code will continue with the execution independantly of it.
So, you just have to put your callback in success callback of each ajax call. What it will do is call your callback function when ajax returns a success. For example:
function a(val, callback) {
$.ajax({
type: "get",
url: "myservlet",
beforeSend: function () {
$('#text1').css({ "color": "red" });
$('#text1').text("Running Graph");
},
data: {
"boxval": val
},
success: function (responseText) {
$('#text1').css({ "color": "green" });
$('#text1').text(responseText);
callback();
}
});
}
Upvotes: 0
Reputation: 106
All the functions has ajax call that is done asynchronously by definition. Try wrapping the ajax calls with some promise mechanism that will allow you the call the callback function when the ajax call is done.
Upvotes: 1
Reputation: 160
$.ajax are promises. You can do it like that:
function a(){
return $.ajax();
}
function b(){
return $.ajax();
and then
a().then(b).then(c)
etc. It should works.
Upvotes: 1
Reputation: 23290
You are doing this:
function blah() {
success: function(responseText) {
// ...
}
callback();
}
Put callback();
inside success
and it will work
function blah() {
success: function(responseText) {
// ...
callback();
}
}
Upvotes: 0