0

I have three ajax calls that give me data which I push into an array.

The second one is called after the first one (in it's success function) so that the array does not get filled asyncronous.

My goal is to have some sort of call back at the very end (marked "END!!" in my code) using the jQuery done() function (or similar). The jQuery done() function however kicks off after the first level has reached it's success function already however.

var ajaxQuery = $.ormon('ajax', {
    url: '../getjson',
    trtyp: 'adm1034',
    dataType: 'json',
    data: {
        clients:1
    },

    success: function(data) {
        console.log("1");

        for (i = 0; i < data.length; i++) {
            var name = data[i].adr1 + " " + data[i].adr2;
            kontaktdata.push({name: name, usrid: data[i].usr});
        }

        $.ormon('ajax', {
            url: '../getjson',
            trtyp: 'adm1034',
            dataType: 'json',
            data: {
                clients:2
            },

            success: function(data) {
                console.log("2");

                for (i = 0; i < data.length; i++) {
                    var name = "(CRM Lead) - " + data[i].adr1 + " " + data[i].adr2;
                    kontaktdata.push({name: name, usrid: data[i].usr});
                }

                $.ormon('ajax', {
                    url: '../getjson',
                    trtyp: 'adm1034',
                    dataType: 'json',
                    data: {
                        clients:3
                    },

                    success: function(data) {
                        console.log("3");
                        for(i = 0; i < data.length; i++) {
                            var name = "(MXVV Kunden) - " + data[i].adr1 + " " + data[i].adr2;
                            kontaktdata.push({name: name, usrid: data[i].usr});
                        }

                        //END!!!!!!!!

                        console.log(kontaktdata);
                    }
                });
            }
        });
    }
});

ajaxQuery.done(function(response) {alert("done");});
Miaonster
  • 1,482
  • 2
  • 18
  • 32
DavidDunham
  • 1,245
  • 1
  • 22
  • 44
  • Would you mind running the three ajax calls in parallel? – Bergi Feb 25 '15 at 12:27
  • I cannot because each ajax returns a dataset. I then fill this into an array, if i run them paralell the array will contain data from dataset1 and then dataset2 and then dataset1 again (mixed up) – DavidDunham Feb 25 '15 at 12:55
  • Not necessarily, no, you can run them in parallel and then concatenate all three data sets in the expected order. – Bergi Feb 25 '15 at 12:57
  • Yes, you are actually right. I can just add them up later individually. – DavidDunham Feb 25 '15 at 13:02

3 Answers3

1

Instead of using done or the success callback, you should use then which chains asynchronous actions and gives you a promise for the last result. In your case, it would look like this:

var kontaktdata = [];
var ajaxQuery = $.ormon('ajax', {
    url: '../getjson',
    trtyp: 'adm1034',
    dataType: 'json',
    data: {clients: 1}
}).then(function(data) {
    console.log("1");
    for (var i = 0; i < data.length; i++) {
        var name = data[i].adr1 + " " + data[i].adr2;
        kontaktdata.push({name: name, usrid: data[i].usr});
    }
    return $.ormon('ajax', {
//  ^^^^^^ return another promise from the callback
        url: '../getjson',
        trtyp: 'adm1034',
        dataType: 'json',
        data: {clients: 2}
    });
}).then(function(data) {
    console.log("2");
    for (var i = 0; i < data.length; i++) {
        var name = "(CRM Lead) - " + data[i].adr1 + " " + data[i].adr2;
        kontaktdata.push({name: name, usrid: data[i].usr});
    }
    return $.ormon('ajax', {
        url: '../getjson',
        trtyp: 'adm1034',
        dataType: 'json',
        data: {clients: 3}
    });
}).then(function(data) {
    console.log("3");
    for(var i = 0; i < data.length; i++) {
        var name = "(MXVV Kunden) - " + data[i].adr1 + " " + data[i].adr2;
        kontaktdata.push({name: name, usrid: data[i].usr});
    }
    return kontaktdata; //END!!!!!!!!
});

ajaxQuery.done(function(result) {
    console.log(result);
    alert("done");
});

OK, this works well, but still looks tedious. What if there were more than only 3 requests to make? You want to encode this in a loop, which is now easily possible:

var ajaxQuery = $.when([]);
for (var client=1; client<=3; client++) (function(client) {
    ajaxQuery = ajaxQuery.then(function(kontaktdata) {
        return  $.ormon('ajax', {
            url: '../getjson',
            trtyp: 'adm1034',
            dataType: 'json',
            data: {clients: client}
        }).then(function(data) {
            console.log(client);
            for (var i = 0; i < data.length; i++) {
                kontaktdata.push({
                    name: data[i].adr1 + " " + data[i].adr2,
                    usrid: data[i].usr
                });
            return kontaktdata;
        });
    });
}(client)); // necessary extra scope for closure

ajaxQuery.done(function(result) {
    console.log(result);
    alert("done");
});

And with promises, it gets even better - you can trivially send all three requests in parallel, and then wait until they're all done, and concat the results:

var requests = [];
for (var client=1; client<=3; client++)
    requests.push($.ormon('ajax', {
        url: '../getjson',
        trtyp: 'adm1034',
        dataType: 'json',
        data: {clients: client}
    }).then(function(data) {
        return data.map(function(d) {
            return {name: d.adr1+" "+d.adr2, usrid: d.usr};
        });
    }));
var ajaxQuery = $.when.apply($, requests).then(function() {
    return [].concat.apply([], arguments);
});
ajaxQuery.then(function(result) {
    console.log(result);
    alert("done");
}, function(err) {
    console.error(err + " went wrong");
});

Using promises has the additional benefit that any ajax fails or asynchronous exceptions will be caught and you can put a catch-like handler in the end.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • 1
    This is much nicer than the accepted answer. I wonder why you converted one `var arr = []; for(...) arr.push` to a `.map` and the other not? Other than that it is very nice. – Benjamin Gruenbaum Feb 25 '15 at 18:07
  • @BenjaminGruenbaum: You mean in the `requests` array in the final snippet? I used a loop because I didn't want to map over a `[1, 2, 3]` literal, and JS still doesn't provide a `range` function :-) – Bergi Feb 25 '15 at 19:24
0

What you could use is a defered promise (http://api.jquery.com/deferred.promise):

Something like this should work (I didn't test it!):

var ajaxQuery = function () {
    var dfd = new jQuery.Deferred();

    $.ormon('ajax', {
            [...]

            $.ormon('ajax', {
                    [...]

                    $.ormon('ajax', {
                            [...]

                            success: function(data) {
                                    dfd.resolve(data);
                            }
                    });
            });
    });

    return dfd;
};

ajaxQuery().done(function (data) { [...] });
0

You can call the done()method on your nested call:

var ajaxQuery = $.ormon('ajax', {
    url: '../getjson',
    trtyp: 'adm1034',
    dataType: 'json',
    data: {
        clients: 1
    },
    success: function (data) {
        console.log("1");
        for (i = 0; i < data.length; i++) {
            var name = data[i].adr1 + " " + data[i].adr2;
            kontaktdata.push({
                name: name,
                usrid: data[i].usr
            });
        }

        $.ormon('ajax', {
            url: '../getjson',
            trtyp: 'adm1034',
            dataType: 'json',
            data: {
                clients: 2
            },
            success: function (data) {
                console.log("2");
                for (i = 0; i < data.length; i++) {
                    var name = "(CRM Lead) - " + data[i].adr1 + " " + data[i].adr2;
                    kontaktdata.push({
                        name: name,
                        usrid: data[i].usr
                    });
                }

                $.ormon('ajax', {
                    url: '../getjson',
                    trtyp: 'adm1034',
                    dataType: 'json',
                    data: {
                        clients: 3
                    },
                    success: function (data) {
                        console.log("3");
                        for (i = 0; i < data.length; i++) {
                            var name = "(MXVV Kunden) - " + data[i].adr1 + " " + data[i].adr2;
                            kontaktdata.push({
                                name: name,
                                usrid: data[i].usr
                            });
                        }

                        //END!!!!!!!!

                        console.log(kontaktdata);
                    }
                }).done(function (response) {
                    alert("done");
                });
            }
        });
    }
});
Danilo
  • 2,676
  • 7
  • 32
  • 36