3

I need to gather some data from the database through AJAX and place it in an array. Unfortunatly I'm unable to archieve this for some reason.

AJAX sends data to retrieve specific data. This data is as follows:

[{"comment_id":154,"comment_text":"Moduleboeken PHP","date_updated":"2015-06-01 10:34:47"},{"comment_id":155,"comment_text":"Moduleboeken JAVA","date_updated":"2015-06-01 10:34:54"}]
[{"comment_id":149,"comment_text":"Werksfeer","date_updated":"2015-06-01 10:33:57"}]
[{"comment_id":152,"comment_text":"Begeleiding Elleke Jagersma","date_updated":"2015-06-01 10:34:27"}]
[{"comment_id":260,"comment_text":"Studievoortgang JAVA","date_updated":"2015-06-01 13:01:15"}]
[{"comment_id":153,"comment_text":"Faciliteiten","date_updated":"2015-06-01 10:34:39"}]

The function to gather this data:

function sendRetrieveAjax(url, data) {
    return new Promise(function(resolve, reject) {
        $.ajax({
            url: url, type: 'post', data: data,                
            success: function(data) {
                resolve(data);
            },
            error: function(request, status, error) {
                reject([{request: request, status: status, error: error}]);
            }
        });
    });
}

Main code runs through 5 DOM elements, gathers an ID from them and uses this in the AJAX send and retrieve function. If this is succesfull it places it in an array.

var elements = $('.note_block');
var dataCollection = new Array();

for(i = 0; i < elements.length; i++) {
    var element = $(elements[i]);
    var data = {
        commenttype_id  :   element.children('#commenttype_id').val(),
        week_id         :   $('#week_id').val()
    }

    sendRetrieveAjax('../functions/getcomments.php', data).then(function(data) {
        console.log(data);
        dataCollection[i] = data;
    });
}
console.log(dataCollection);

The array unfortunatly is empty, while the console shows the correct data.

Can someone enlighten me?

Smoothal
  • 45
  • 1
  • 11
  • FYI, [jQuery.post](http://api.jquery.com/jQuery.post/) returns an object which implements it's own [Promise interface](http://api.jquery.com/category/deferred-object/) – CodingIntrigue Jun 02 '15 at 11:28
  • @RGraham, Didn't know that, but now I do, thanks! – Smoothal Jun 02 '15 at 11:32
  • @dfsq, that post has helped me towards the promise method of my ajax call. But it doesn't solve my problem. – Smoothal Jun 02 '15 at 11:35
  • 1
    Your problem is that you are trying to populate `dataCollection` in `then` block but `console.log(dataCollection)` outside. However `dataCollection` is not yet populated by that time. – dfsq Jun 02 '15 at 12:44
  • @Smooth, please see the below answer – Mohamed Shaaban Jun 02 '15 at 13:28

2 Answers2

0

You have two problems

  1. You need to bound the value of i to the sendRetrieveAjax
  2. You need to print the value of dataCollection after filling it (note the use of promise)

To solve the first problem you need to use IIFE (Immediately-Invoked Function Expression)

for(i = 0; i < elements.length; i++) {
    var element = $(elements[i]);
    var data = {
        commenttype_id  :   element.children('#commenttype_id').val(),
        week_id         :   $('#week_id').val()
    }

    (function(_i) {
        sendRetrieveAjax('../functions/getcomments.php', data).then(function(data) {
            console.log(data);
            dataCollection[_i] = data;
        });
    })(i);
}

And to solve the second problem, you can use an array or promises to keep all request's promises in it, and execute them either sequential or parallel

var requests = []
;

for(i = 0; i < elements.length; i++) {
    var element = $(elements[i]);
    var data = {
        commenttype_id  :   element.children('#commenttype_id').val(),
        week_id         :   $('#week_id').val()
    }

    // No need to store the URL, just store the data
    requests.push(data);
}

requests = requests.map(function(data) {
    return sendRetrieveAjax('../functions/getcomments.php', data);
});

Promise.all(requests).done(function(responses) {
    console.log(responses);
    dataCollection = responses;
}, function(err) {
});
Mohamed Shaaban
  • 1,129
  • 6
  • 13
0

You need to map each individual response to correct array index. The most optimal solution in this case would be to use $.when to provide an array of promises and the get centralized response object with ordered response data objects.

I also simplified sendRetrieveAjax as $.ajax already returns promise object:

function sendRetrieveAjax(url, data) {
    return $.ajax({
        url: url,
        type: 'post',
        data: data
    });
}

var promises = $('.note_block').map(function(i) {
    return sendRetrieveAjax('../functions/getcomments.php', {
        commenttype_id: $(this).children('.commenttype_id').val(),
        week_id: $('#week_id').val()
    });
}).get();

$.when.apply(null, promises).then(function() {
    var dataCollection = $.map(arguments, function(data) {
        return data[0];
    });
    console.log('Data Collection', dataCollection);
});

Another thing, don't duplicated ids, use .commenttype_id classes instead.

Here is a demo: http://plnkr.co/edit/r9NnlxIQjUhNvTYwfLy7?p=preview

dfsq
  • 191,768
  • 25
  • 236
  • 258