Consecutive function call while one of them uses setTimeout

I want to call the three functions someTask1 , someTask2 and someTask3 in this order. However, the someTask2 function includes an Ajax call and continues to call it recursively with setTimeout if the required value is not returned. The code is as follows:

 doListOfTasks: function(myparam){ var someObj = someTask1(myParam); someTask2(someObj); someTask3(someObj); }, someTask2: function(someObj){ $.ajax({ url: "someUrl.do", type: "POST", data: ({"id": rowObject.instanceId}), dataType: "json", async:false, success: function(res){ if(res.prop1 != 'desired'){ setTimeout(function(){someTask2(someObj);}, 2000); } } } ); }, 

As you might have guessed, the execution of this code does not someTask2 for someTask2 to return before calling someTask3 .

I want the code inside doListOfTasks executed sequentially. How can i do this?

Also, I don't want to use someTask3 code in success for hard code. For instance. I do not want to do this:

  success: function(res){ if(res.prop1 != 'desired'){ setTimeout(function(){someTask2(someObj);}, 2000); }else{ someTask3(someObj); } } 

How can this be achieved?

thanks


Edit # 1

The problem is not the ability to call functions ... but the problem is synchronization. I want someTask2 to complete everything it does, and only then someTask3 is called.

someTask2 causes reuse of setTimeout ... I assume this causes a new thread, and someTask2 returns after the first call ... of someTask3 trigger in the main thread. However, a separate thread generates (and kills) in each setTimeout call until the required criteria are met.

That is why, while someTask2 is still cyclical, a call to someTask3 is triggered.

I don’t know how right I am.

+4
source share
2 answers

You can achieve this using Deferred in jquery:

 $.when(someTask1(), someTask2(), someTask3()).then(successFunc, errorFunc); 

You need to return the created custom .Deferred object with the promise value.

 someTask2: function(someObj) { var def = $.Deferred(); $.ajax({ url: "someUrl.do", type: "POST", data: ({"id": rowObject.instanceId}), dataType: "json", async:false, success: function(res){ if(res.prop1 != 'desired'){ setTimeout(function(){someTask2(someObj);}, 2000); } else { def.resolve(res); } } } ); return def.promise(); } 

So for example:

 function someTask1() { var def = $.Deferred(); def.resolve('i\'m data resolved from task1'); return def.promise(); } function someTask2(someObj) { var def = $.Deferred(); var count = 0; var f = function() { console.log(++count); if (count > 2) { def.resolve('whoop we got the value we wanted in task 2 after many tries: ' + count); } else setTimeout(f, 1000); }; f(); return def.promise(); } function someTask3() { var def = $.Deferred(); def.resolve('and hello from task3!'); return def.promise(); } var success = function(x) { console.log('success:', arguments); }; var error = function() { console.log('oh no an error occured in one of the tasks.'); }; $.when(someTask1(), someTask2(), someTask3()).then(success , error); 

Will show

 1 2 3 success: ["i'm data resolved from task1", "whoop we got the value ...k 2 after many tries: 3", "and hello from task3!"] 

fiddle available http://jsfiddle.net/garreh/29SW7/

+2
source

You can pass someTask2 . For instance:

 someTask2: function(someObj, callback){ $.ajax({ url: "someUrl.do", type: "POST", data: ({"id": rowObject.instanceId}), dataType: "json", async:false, success: function(res){ if(res.prop1 != 'desired'){ setTimeout(function(){someTask2(someObj, callback);}, 2000); } else { if (callback != null) { callback(); } } } } ); } 

Then just pass someTask3 as a callback:

 someTask2(someObj, function (){ someTask3(someObj); }); 
+1
source

All Articles