4

following problem - I have to call ajax function number of times, and when all functions are complete, get all results into array. I came up with this:

function doAjax(xx){
var xdata = {json: $.toJSON({name: xx}),
            delay: 1};
return $.ajax({
    url:"/echo/json/",
    data:xdata,
    type:"POST"
});

}

var carr = [doAjax('a'),doAjax('b'),doAjax('c'),doAjax('d')]
var result = [];

$.when( carr )
    .done(function(data){
        console.log(data);
        $.each(data, function(ix,val){
            console.log(val.name);
        });
    });

Fiddle here: http://jsfiddle.net/Fkd9n/

All seems to be working fine, the "console.log(data)" writes out the objects with response text, but the "console.log(val.name)" is always "undefined". So how to joint all results in one array once all calls are done?

Thank you!

Markus
  • 95
  • 2
  • 11

2 Answers2

8

If you know how many Ajax-Calls you have, simply use $.when()

$.when(doAjax('a'),doAjax('b'),doAjax('c'),doAjax('d'))
.then(function(result_a,result_b,result_c,result_d) {
    console.log("Result from query a: " + result_a);
    console.log("Result from query b: " + result_b);
    console.log("Result from query c: " + result_c);
    console.log("Result from query d: " + result_d);
});

If you don't know how many ajax-calls you will have, you can manage the deferred objects by yourself.

// altered version of doAjax()
function doAjax(number,dObject) {
    var xdata = {json: $.toJSON({name: number}), delay: 1};
    $.ajax({
        url:"/echo/json/",
        data:xdata,
        type:"POST",
        success: function(data) {
            results.push(data);
            dObject.resolve();
        }
    });
}

// array that will contain all deferred objects
var deferreds = [];

// array that will contain all results
var results = [];

// make the ajax calls
for (var i = 0; i < someNumber; i++) {
    var dObject = new $.Deferred();
    deferreds.push(dObject);
    doAjax(i,dObject);
}

// check if all ajax calls have finished
$.when.apply($, deferreds).done(function() {
    console.log(results);
});

The magic comes with the function apply() which makes an array to arguments for a function.

Zim84
  • 3,404
  • 2
  • 35
  • 40
4

You can use pipe function to process resulting data.

$.when.apply($, carr).pipe(function(){
    console.log(arguments);
    return $.map(arguments, function(item){return item[0]});
})
    .done(function(data){
        console.log(data);
        $.each(data, function(ix,val){
            console.log(val.name);
        });
    });​

http://jsfiddle.net/Fkd9n/6/

Yury Tarabanko
  • 44,270
  • 9
  • 84
  • 98
  • Yury thank you for your solution, It works as expected and I like it for the simplicity. However I am going to accept the "Zim84's" answer as it fits more my needs. – Markus Dec 17 '12 at 12:33
  • FYI: _As of jQuery 1.8, the deferred.pipe() method is deprecated. The deferred.then() method, which replaces it, should be used instead._ [deferred.pipe](https://api.jquery.com/deferred.pipe/) – jwillmer Apr 22 '15 at 12:11