0

I would like to ".push" the result of "$.post" into an array.

I've tried the following code, but in appears that cats.push(data); doesn't work inside the $.post function, I can confirm with alert(data); that data variable is not empty but at the end the "cats" array is empty

        $('[id^="mul-"]').click(function () {
                cats = [];
                $(this).toggleClass('selected');
                $(".selected").each(function(){

                    $.post( "/index.php?do=getcatname&id=" + this.id.slice().replace(/mul-/,''), function( data ) {
                        cats.push(data);
                        alert(data);
                    });
                });

                ms = cats.join(",");
                alert(ms);
        });
Orlo
  • 828
  • 2
  • 11
  • 28

1 Answers1

4

The first letter A in AJAX stands for Asynchronous. This means that the $.post method returns immediately and the success callback might be invoked much later. Here you seem to be performing multiple AJAX requests and inside the success callback of each AJAX request you seem to be adding some element to the array. So it isn't until the last AJAX request has finished executing that you can use the results of this array.

You could use deferred execution that was introduced in jQuery 1.5 in order to aggregate the results of multiple AJAX calls:

$('[id^="mul-"]').click(function () {
    $(this).toggleClass('selected');

    // get an array of the ids that will be used for each AJAX call
    var ids = $(".selected").map(function() {
        return this.id.slice().replace(/mul-/,'');
    });

    // declare the variable that will hold the result
    var categories = [];

    var ajaxCall = function(i) {
        return $.ajax({
            url: '/index.php',
            type: 'POST',
            data: { do: 'getcatname', id: i }
        }).done(function (res) {
            categories.push(res);
        }); 
    };

    $.when.apply($, ids.map(function(i) {
        return ajaxCall(i);
    })).then(function() {
        // Here you could use the categories array:
        var result = categories.join(', ');
        alert(result);
    });
});

This being said you should bear in mind that making multiple small AJAX request is worst in terms of performance than having a single larger AJAX request. This means that you should modify your index.php script so that it is capable of taking a list of ids as parameter (instead of a single id) and getting you back the list of corresponding categories. Then inside your .click handler you will build this list of ids and send a single AJAX request to your server. This is basically pushing the logic to your server which will be faster than your current architectural approach.

So here's how a much improved version of your code might have looked like:

$('[id^="mul-"]').click(function () {
    $(this).toggleClass('selected');

    // get an array of the ids that will be used for each AJAX call
    var ids = $(".selected").map(function() {
        return this.id.slice().replace(/mul-/,'');
    });

    $.ajax({
        url: '/index.php',
        type: 'POST',
        data: { do: 'getcatnames', ids: ids },
        success: function(categoryNames) {
            alert(categoryNames.join(', '));
        }
    });
});

Notice how we are sending the entire list of ids to your sevrer side script which will take care of returning the list of corresponding category names as a JSON array: ['cat 1', 'cat 2', 'cat 3', ...].

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928