5

I want function A to finish execution and only after that function B should start executing. When I call function A and then function B, it seems both are executing simultaneously. And after function B completes, I want to call a third function update_dropdown().

My code looks like this:

function A {
    for (var i = 0; i < 5; i++) {
        var promise = $.get(url+i);
        $.when(promise).then(function () {
            $.post(url);
        });
    }
}
function B {
    var x = $.get(url);
    var promise = $.post(url+x);
    $.when(promise0).then(function () {
        update_dropdown();
    });
}

Please can you tell me how I can make these 3 function calls happen sequentially.

10
  • 1
    Not entirely sure what your goal is, can you explain a little more? Commented May 4, 2014 at 0:14
  • 1
    Assuming: 1. You call function A, want to wait for the $.get to complete, then you want to call function B and finally once B completes you want to call update_dropdown()? Commented May 4, 2014 at 0:20
  • 1
    If you want an accurate answer, you really have to detail what you want the calling sequence to be. Your code doesn't make a whole lot of sense (and it's pseudo-code) so it isn't very clear what sequence you actually want things to happen in. For example, in A(), do you want five $.get() operations in parallel and then when they all complete, a $.post() operation? In B(), do you really want to do a $.get() and then without waiting for anything, do a $.post()? Commented May 4, 2014 at 2:19
  • 1
    Yes @Pepto your assumption is correct, "You call function A, want to wait for the $.get to complete, then you want to call function B and finally once B completes you want to call update_dropdown()" Commented May 4, 2014 at 6:02
  • In function-A, I want 5 sequential get&post requests. First get then post. This has to happen 5times. Then function-B, has to execute. In B there is a single $get, from which I get some value, and then post that value. (sorry this part is not shown in my code, caused some confusion there.) Then call function update_dropdown(). Commented May 4, 2014 at 6:09

5 Answers 5

4

OK, it's getting a little bit clearer what you actually want (based on your recent comments to address clarifying questions) though there are still at least two options open.

For an operation like this, you probably want to take advantage of a number of promise features:

  1. jQuery's Ajax calls already return a promise so you can just use those directly
  2. To serialize operations, you can just chain multiple promise operations together
  3. To make async operations serialize properly, you can return a promise from a .then() handler and the master promise will resolve only when all the chained promises have resolved (kind of a built-in $.when() without having to explicitly call $.when()).
  4. You can chain as many operations together as you want and the master promise will tell you when they are all done.
  5. If you return promises from both A() and B(), then the callers of those functions can monitor when they are done with promise methods which then lets you chain A().then(B) to sequence those two.
  6. When you sequence operations with chaining, the prior methods resolve data is passed to the next .then() handler function in the chain as the first argument to the .then() handler function so if you need the prior data for the next operation, it is right there to use.

So, with all those capabilities, it's just a matter of putting the right scaffolding around the code to implement the exact sequencing you want. Here are two different options:


Option 1: If you want to serialize everything in A() so that all 10 requests happen in serial fashion (the next one proceeds only when the prior one is done), then it could look like this:

// serialize all requests
function A() {
    var p = $.get(url).then(function(data) {return $.post(url)});
    for (var i = 1; i < 5; i++) {
        // chain four more pairs of requests onto the original promise
        p = p.then(function() {return $.get(url)})
             .then(function(data) {return $.post(url)});
    }
    // return the promise so callers can monitor when A() is done
    return p;
}


function B() {
    // sequence these three operations one after the other
    return ($.get(url)
       .then(function(data) {return $.post(url + x)})
       .then(update_dropdown)
    );
}

// run them both, one after the other
A().then(B);

Option 2: If you want the 5 pairs of requests in A() to run in parallel, with only the last part of A() waiting until the 5 pairs of requests are done, then it could look like this:

// parallelize pairs of requests
function A() {
    var promises = [];
    for (var i = 0; i < 5; i++) {
        // execute 5 pairs of requests where each pair is serialized in itself
        promises.push($.get(url).then(function(data) {return $.post(url)}));
    }
    // return a promise that resolves only when all the other promises are done
    return $.when.apply($, promises);
}

function B() {
    // sequence these three operations one after the other
    return ($.get(url)
       .then(function(data) {return $.post(url + x)})
       .then(update_dropdown)
    );
}

// run them both, one after the other
A().then(B);

These use the concept that if you return a promise from a .then() handler function, then it will chain multiple async operations together and the master promise is only resolved when all the chained operations are resolved. This is very powerful for sequencing multiple ajax operations and you can even do it for operations in a loop like you have.

Sign up to request clarification or add additional context in comments.

7 Comments

I tried option2. My requests are not getting generated in the expected sequence. Also requests from function A and B are getting mixed. It is not coming as all requests from function A, followed by all requests from function B. This is what I can see in the network requests log.
@PriyankaA - Option 2 is parallel. From your earlier comments, you want option 1 so things in A() are serialized. Also, can you show us your actual code? We can't really debug pseudo-code. If requests from function A() and B() are getting mixed, then something is not implemented properly because neither option 1 or option 2 will do that.
@PriyankaA - I don't know what you intended to post, but that's about a 100x100 image that is unreadable. If you're posting code, don't do screenshots. Use the edit button and add it to your question. I can't really help you debug without seeing your actual code.
Yes, I completely agree with you. In any case requests from function A and B should not be mixed, may it be option 1 or 2. Here is the link to my code
@PriyankaA - The first issue I see is that unattachSTARs() should end with return $.when.apply($,promises);, not return $.when.apply($.promises);. Note the comma instead of the period.
|
3

Something like this should work

function A {
    var xhr = [];

    for (var i = 0; i < 5; i++) {
        xhr.push( $.get(url) );
    }

    $.when.apply($, xhr).then(B);
}

function B {

    $.get(url).done(function(x) {
        $.post(url + x).done(update_dropdown);
    });

}

Note the use of an array to keep the promises in, then using $.when with apply() to fire a callback when all the ajax requests in the loop has finished.

5 Comments

You don't have the same functionality in functions A() and in B() as the OP and are missing two operations.
@jfriend00 - In function A the $.when call is inside the loop in the OP's code, calling the B function for each request, I assumed that was the problem and that the point was to move it out of the loop. In the B function I'm missing a call to $.get(url), otherwise it's the same, but the OP is calling $.get(url) five times in A, so I didn't think it very pertinent to call that function again in B, and if it was, the procedure to wait for both calls to finish would be the same as in A
Yeah, I guess it isn't entirely clear what calling sequence the OP actually wants. FYI, it probably doesn't matter for .when(), but you simulate $.when(...) more accurately with $.when.apply($, xhr); where you pass $ instead of undefined so this is set to $.
Also, $.when( $.post(url) ).then(update_dropdown); can just be: $.post(url).then(update_dropdown);
It's probably a good idea to return from each function, that way, you will be able to hook on it all being done and compose it.
1

Assumptions assumptions ...

Let's assume that :

  • the url for every get is the same as that for its corresponding post
  • the urls for each get-post pair should vary
  • the five get-post pairs in A can occur in parallel and we are not interested in the returned data

First, a utility function :

function getThenPost(url, appendToURL) {
    return $.get(url).then(function(x) {
        return (appendToURL) ? $.post(url + x) : $.post(url);
    });
}

then A and B, both of which call the utility :

function A(urls) {
    return $.when.apply(null, urls.map(function(url) {
        return getThenPost(url, false);
    }));
}
function B(url) {
    return getThenPost(url, true);
}

and finally an expression that calls A and B :

A(['/path/0', '/path/1', '/path/2', '/path/3', '/path/4']).then(function() {
    B('/path/5');
}).then(update_dropdown);

It should be reasonably simple to adjust this code if assumptions 1 and 2 are incorrect.

If assumption 3 is incorrect then A will require more extensive modification.

1 Comment

Correction made to function A.
0

We can call our choice function in our way using jquery Deferred Object.

It is very simple let see successfully run example:

<body>
<script
    src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script type="text/javascript">

// I want to call function in order of  f1,f2,f3,f4 every time when i will execute this html page.

    promise = f1().then(f2).then(f3).then(f4); // Add handlers to be called when the Deferred object is resolved, rejected, or still in progress.

    function f1() {
        var d = $.Deferred();

        setTimeout(function() {
            // our code here....
            alert("1");
            console.log("1");
            d.resolve(); // resolve() :Resolve a Deferred object and call any doneCallbacks with the given args.
        },1000); // You set some time for each method.
        return d.promise(); //promise(): Return a Deferred’s Promise object.

    }
    function f2() {
        var d = $.Deferred();

        setTimeout(function() {
            alert("2");
            console.log("2");
            d.resolve();
        },1000);
        return d.promise();
    }
    function f4() {
        var d = $.Deferred();

        setTimeout(function() {
            alert("4");
            console.log("4");
            d.resolve();
        },1000);
        return d.promise();
    }
    function f3() {
        var d = $.Deferred();

        setTimeout(function() {
            alert("3");
            console.log("3");
            d.resolve();
        },1000);
        return d.promise();
    }


</script>

2 Comments

Uh, pipe is deprecated since years?
Oh thanks, I got it, pipe() is deprecated in jquery 1.8. So i just edited with another powerful method then() of deferred.then().
-1

Javascript without extra work is single threaded. that means functions are not able to be executed simultaneously. but the problem is that the $.get() and $.post() calls are asynchronous. that means they are executed whenever the requested data arrives your client. (first come first serve)

an solution would be to execute function B after all the results ob A arrived, or to hold back all results and handle all data at once then run update_dropdown().

1 Comment

I think they understand that and are simply asking how to do that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.