3

I know this question has been asked several times, however I can't seem to get the solutions to work with my code: Wait till a Function with animations is finished until running another Function, jquery wait for multiple complete events, Wait for the end of TWO asynchrounous functions before firing a third (jQuery Deferred ?)

Basically, I would like to call four functions successively:

#1
function getJason() {
 $.getJSON(rgUrl1,function(json1){
   rgJson1 = json1; ...etc.
 });      


#2
function combineJason() {
  //code to combine 
});


#3
function divideArray() {
  //code to divide stuff 
});


#4
function doOtherStuff() {
  //code to do some other stuff
});

I need #1 to finish before calling #2, #2 to finish before #3, and #3 to finish before #4. Past posts have led me to believe that I should use deferrds and promises. I've read through the documentation http://api.jquery.com/category/deferred-object/ and have experimented with examples without success:

function testing() {

 var deferredObj = $.Deferred();
 var test = getJson()
 var function1 = function () {

  test.done(function(){

    deferredObj.resolve();

    return deferredObj;
   });

  }

  deferredObj.done(function(){
   combineJson();
 });
}; 

Furthermore, most of the examples deal with two functions, whereas I need to call several. I've also noticed that some responses incorporate "setTimeout". I'm a bit leery, perhaps unnecessarily, about using anything with a timer or pause or delay. Wouldn't I then have to guess how long the function will take. What about if one user's computer/connection is slower or something?

Community
  • 1
  • 1
user3080392
  • 1,194
  • 5
  • 18
  • 35
  • I would be inclined to use something link WatchJS ... https://github.com/melanke/Watch.JS (look into Promises). – rfornal Dec 20 '14 at 19:01
  • Have you taken a glance at [`Promises`](http://www.html5rocks.com/en/tutorials/es6/promises/)? – Anthony Forloney Dec 20 '14 at 19:02
  • `getJason()` is clearly asynchronous. The big question to ask yourself is whether `combineJason()`, `divideArray()` and `doOtherStuff()` are asynchronous or synchronous? – Roamer-1888 Dec 20 '14 at 19:06
  • 1st: you're right, using timeouts is not an option! I find your question a bit unclear how the four functions should be called; where the input data comes from and and where the output data goes to. But since you've mentioned that you've looked at Deferreds already let me point you to the sentence in the docs stating `"[...] Since deferred.done() returns the deferred object, other methods of the deferred object can be chained to this one, including additional .done() methods. [...]"` – try-catch-finally Dec 20 '14 at 19:06
  • Not that article specifically, however I did read http://blog.mediumequalsmessage.com/promise-deferred-objects-in-javascript-pt1-theory-and-semantics and http://joseoncode.com/2011/09/26/a-walkthrough-jquery-deferred-and-promise/ I was still somewhat confused afterwards. I tried piecing together their info and responses from previous posts, but no success. – user3080392 Dec 20 '14 at 19:06
  • @ try-catch-finally The first function gets json data from different urls, it passes the data to the second. The second takes the individual jason files and combines them. That combination/array is then passed to the third where I do some editing. Finally the edited array gets passed to the fourth function where I'll do something else, like further editing or posting the results to my page. – user3080392 Dec 20 '14 at 19:13
  • There is an answer for http://stackoverflow.com/questions/17216438/chain-multiple-then-in-jquery-when which might be helpful for your case. – axel.michel Dec 20 '14 at 19:13
  • When I get your description correctly, you'll have only one async function, rest is synchron, isn't it? So why don't you call one from the other? – axel.michel Dec 20 '14 at 19:15
  • @michel Yes, the first is async and the others, as of now, are synchron. Could you give me an example of what you mean. Also, in the end, I'd like the code to work if I have more than one async function. – user3080392 Dec 20 '14 at 19:20

2 Answers2

3

jQuery's ajax functions already return a promise. So you do not need to create new deferred objects if you are using jquery's ajax functions.

To get your functions called in succession: call the .then method for however many functions you need to call. If one or more of your functions need to do some async task then just return a promise, the deferred object will wait to call the next then callback till the returned promise resolves. Each then callback will get passed the data returned in the previous then (or in the case of returned promise the resolved data)

$.getJSON(rgUrl1,function(json1){
   rgJson1 = json1; ...etc.
}).then(combineJason)
.then(divideArray)
.then(doOtherStuff);      

//#2
function combineJason(someData) {
  //code to combine 
  return $.getJSON("url to some other json endpoint");
}

//#3
function divideArray(someData) {
  //code to divide stuff 
  //this function is sync so just return some data
  return someNewData;
}

//#4
function doOtherStuff(someData) {
  //code to do some other stuff
  //this function is async so return a promise;
  return $.getJSON("url to some other json endpoint");
}

JSFiddle Demostrating mixed async/sync succession

Patrick Evans
  • 41,991
  • 6
  • 74
  • 87
  • can you explain if the first call takes more time http://jsfiddle.net/nikhilsreeni/ffjkcmqL/1/ – Nikhil K S Sep 27 '17 at 13:23
  • 1
    @NikhilKS you changed the first callback to one that uses an async operation, the return inside the setTimeout callback is meaningless as it isn't returning to anything. Re-read the second paragraph of my answer. If your callback needs to do some async operation and you need the chain to wait for it to finish you need to return a new promise within that callback – Patrick Evans Sep 27 '17 at 21:24
2

To call them successively is quite easy, you don't need to wait for multiple async things but only for the previous one each.

You'd do

function getJason() {
    return $.getJSON(rgUrl1);
}
function combineJason(json1) {
    //code to combine 
}
function divideArray() {
    //code to divide stuff 
}
function doOtherStuff() {
    //code to do some other stuff
}

getJason().then(combineJason).then(divideArray).then(doOtherStuff);

which would be very similar to

doOtherStuff(divideArray(combineJason(getJason())));

only that it takes care to defer the computation (as a callback) if one result is asynchronous (in here, the $.getJSON in getJason).

Bergi
  • 630,263
  • 148
  • 957
  • 1,375