Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple ajax calls inside a each() function.. then do something once ALL of them are finished?

Let me explain my code a little bit (Excuse me if somethings wrong, I've just written this example from scratch, it is very close to what I currently have).

HTML:

<form id="form">
    <!-- Friend 1 -->
    Name 1: <input type="text" name="friendName1" id="friendName1" class="friendName" value=""><br />
    Email 1: <input type="text" name="friendEmail1" id="friendEmail1" value=""><br /><br />
    <!-- Friend 2 -->
    Name 2:<input type="text" name="friendName2" id="friendName2" class="friendName" value=""><br />
    Email 2:<input type="text" name="friendEmail2" id="friendEmail2" value=""><br /><br />
    <!-- Friend 3 -->
    Name 3:<input type="text" name="friendName3" id="friendName3" class="friendName" value=""><br />
    Email 3:<input type="text" name="friendEmail3" id="friendEmail3" value=""><br /><br />
    <!-- Friend 4 -->
    Name 4:<input type="text" name="friendName4" id="friendName4" class="friendName" value=""><br />
    Email 4:<input type="text" name="friendEmail4" id="friendEmail4" value=""><br /><br />
    <!-- Submit -->
    <input name="submit" type="submit" value="Submit">
</form>

JS:

$("#form").submit(function(){

    $(".friendName[value!='']").each(function(){
        var idEmail = 'friendEmail' + $(this).attr("id").replace('friendName','');
        if($("#"+idEmail+"[value!='']").length > 0){
            var name = $(this).val();
            var email = $("#"+idEmail).val();

            // Submit the ajax request
            $.ajax({ 
                type: 'POST', 
                url: 'ajax/url', 
                data: {
                    name: name,
                    email: email
                },
                success: function(json) {
                    // Log a console entry if our ajax request was successful
                    console.log(name + " was submitted via ajax");
                }
            });
        }
    });

    // Redirect the user to the thank you page
    setTimeout( function() { window.location= '/thanks'; }, 2000 );

});

JSFiddle (redirect removed and ajax call replaced with console log for fiddle)

http://jsfiddle.net/cM5PX/

The HTML is a simple form, with friend name and friend email input fields.

The JS has an each function, which if the name and associated email have values, it runs an ajax call.

I need a way for these ajax calls to run (there could be 1 loop, there could be 15) and then after they have all finished, redirect to a new page.

The current way I'm doing it is horrible, as all of the ajax calls do not finish running before the page redirects.

What can I do to make this better? It needs to be fool proof and ONLY redirect once all of the ajax calls have finished (success or error, it doesn't matter - it just needs to redirect once its finished).

I have tried using async: false but it doesn't seem to make a difference.

I've thought about putting a counter in the each function and a counter in the ajax success function and if they both match, then do the redirect, but I am looking for some more experienced guidance.

like image 327
Latox Avatar asked Jan 04 '12 11:01

Latox


People also ask

How do I stop multiple AJAX calls?

}); If isLoading is false, the AJAX call starts, and we immediately change its value to true. Once the AJAX response is received, we turn the value of that variable back to false, so that we can stop ignoring new clicks.

How do you check if all AJAX calls are completed?

jQuery ajaxStop() Method The ajaxStop() method specifies a function to run when ALL AJAX requests have completed. When an AJAX request completes, jQuery checks if there are any more AJAX requests. The function specified with the ajaxStop() method will run if no other requests are pending.

How do I make jQuery wait for an AJAX call to finish before it returns?

If you don't want the $. ajax() function to return immediately, set the async option to false : $(". my_link").

Can we execute run multiple AJAX requests simultaneously in jQuery?

There is a requirement to make multiple AJAX calls parallelly to fetch the required data and each successive call depends on the data fetched in its prior call. Since AJAX is asynchronous, one cannot control the order of the calls to be executed.


2 Answers

Use deferred objects:

$("#form").submit(function(e){

    e.preventDefault();

    var calls = [];

    $(".friendName[value!='']").each(function(){
        // Submit the ajax request
        calls.push($.ajax({ 
            type: 'POST', 
            url: 'ajax/url', 
            data: {
                name: name,
                email: email
             },
             success: function(json) {
                // Log a console entry if our ajax request was successful
                console.log(name + " was submitted via ajax");
             }
         }));
    });

    $.when.apply($, calls).then(function() {
        window.location= '/thanks';
    });
});
like image 72
Felix Kling Avatar answered Oct 13 '22 23:10

Felix Kling


Ok, this is fairly easy since you're using jQuery. jQuery comes with an integrated promise maker which also is wired up with jQuery's Ajax calls. What does that mean? Well, we can easily go like this:

var requests = [ ];

// ...

// Submit the ajax request
requests.push($.ajax({ 
    type: 'POST', 
    url: 'ajax/url', 
    data: {
        name: name,
        email: email
    },
    success: function(json) {
        // Log a console entry if our ajax request was successful
        console.log(name + " was submitted via ajax");
    }
}));

// at this point we filled our array with jXHR objects which also inherit the promise API

$.when.apply( null, requests ).done(function() {
    document.location.href = '/thanks';
});

Note: The above code will only fire, if all requests completed successfully. If you need to handle the case if one ore more requested failed, use .then() or .fail() instead of .done(), too.

like image 21
jAndy Avatar answered Oct 13 '22 23:10

jAndy