1

How can I make second AJAX request in the function below asynchronous instead of synchronous? result is a string that should start with 'start of string' and end with 'end of string' but in the middle of the string will be the results of an initial AJAX request that is being iterated.

Foo = {
    foo: function() {
        $(document).on("change", '.foo', function(e) {
            e.preventDefault();
            $.ajax({
                url: "foo.php",
                success: function(rows) {
                    $.each(rows, function() {
                        var result = 'start of string'; // START
                        $.ajax({
                            url: "bar",
                            async: false, // I DON'T want this
                            success: function(data) {
                                result += data; // MIDDLE
                            }
                        });
                        result += 'end of string'; // END
                    });
                }
            });
        });
    }
}

Thank you.

ale
  • 11,636
  • 27
  • 92
  • 149

4 Answers4

3

You can take advantage of jquery deferred objects. You can have two different ajax calls in different functions and then you can use .done() method to make sure you get the final string once both the ajax calls have been completed.

Read more here:

vivek
  • 1,944
  • 1
  • 17
  • 26
3

In jquery the way to chain asynchronous calls which are executed one after other, is using promise.then(), which was also called promise.pipe() in previous jquery versions.

Foo = {
    foo: function() {
        $(document).on("change", '.foo', function(e) {
            e.preventDefault();

            var param1 = {url: "foo.php"};
            var param1 = {url: "bar"};

            $.ajax(param1)
               .then(function(rows) {
                    var result = 'start of string'; //START
                    var fn = function(data) {
                       result += data;
                    }
                    var last, first;
                    $.each(rows, function() { // rows should be iterable
                        if (!last) { 
                           first = last = $.ajax(param2).done(fn)
                        } else {
                           last = last.then(function(res) {
                              return $.ajax(param2).done(fn);
                           });
                        }
                    });
                    last.done(fn).done(function() {
                       result += 'end of string'; // END
                    });
                    return first;
               });
        });
    }
}
Manolo Carrasco Moñino
  • 9,723
  • 1
  • 22
  • 27
2

The easiest way to do this is indeed by using deferred objects, the example of your JavaScript using the jQuery when and done deferred statements;

$.when(ajaxCallOne()).done(ajaxCallTwo(rows));

function ajaxCallOne() {
    return $.ajax({
                url : "foo.php",
                async: true
            });
}

function ajaxCallTwo(rows) {
    var result = 'start of string';
    $.each(rows, function() {
        $.ajax({
            url : "bar",
            async : true,
            success : function(data) {
                result += data; // MIDDLE
            }
        });
        result += 'end of string'; // END
    });

    return result;
}

I'm not a JavaScript nor jQuery expert, but I think you should look at those deferred objects.

frbl
  • 1,172
  • 11
  • 17
  • 1
    Note that ajaxCallTwo will fire all ajax requests at the same time and not sequentially – Manolo Carrasco Moñino Mar 21 '13 at 00:50
  • @Manolo, does it? The when.done will take care of executing callTwo after call one has terminated right? Which is the promise design pattern described in Tharwat's post. – frbl May 16 '13 at 07:50
2

I think you should look at the javascript promise design pattern

let me explain little to you:

This promise is a sort of proxy, representing the future result of the operation. You would then register a callback on the promise, which will be executed by the promise once the operation does complete and the result is available.

Using jQuery you can define promise like this:

var promise = $.getJSON('url');

then using your promise variable you can define what to do when your request is done or failed or even do some function in case it failed or succeded.

promise.done(function(s) {alert('done successfully'); });
promise.fail(function(){ alert('get failed!'); });
promise.always(function(){ alert('this 'll executed anyway!'); });

there are plenty of tutorials on it

Promises and Deferred objects in jQuery

jQuery: Deferred Object

javascript promises

What is the benefit of a 'promise' abstraction in CommonJS?

Community
  • 1
  • 1
ebram khalil
  • 8,252
  • 7
  • 42
  • 60