1

I am trying to build an array from the responses of a jquery post. I have the following code:

categories_names = [];
$(categories).each(function(index, category_id) {
    $.post('/modules/blog/add_post_categories', {post_id:result.result, category_id:$(category_id).val()},
    function(result)
    {
        categories_names.push = result;
    });
}).promise().done(function() {
    var final_cats = categories_names.join("");
    console.info(final_cats);
});

The post request inserts the category id into a table and returns the name of that category formatted like <li>Category Name here</li> so that once the array is built and all categories selected (by checkbox in the form previous to this) are entered into the database, the array can be joined and inserted as html to the final view. At the moment the code is just printing it out in the console as you can see but as you've probably guessed, it returns (an empty string)

I know this is most likely a scope issue since that's the area of javascript that still totally baffles me, so I'm hoping someone can shed some light on it.

11
  • Is the post happening asynchronously? Commented May 29, 2013 at 17:15
  • Are you sure the post is actually returning anything? Can you see it in the developer tools? Commented May 29, 2013 at 17:16
  • @MikeChristensen - I assumed not... but that would explain it... should I change the post to $.ajax so I can control that? Commented May 29, 2013 at 17:17
  • @MattBurland - yes... it's definitely returning the <li> Commented May 29, 2013 at 17:18
  • 1
    Your .promise().done(...) isn't doing what you think it is. It's simply resolving instantly because there are no animations on the elements you are iterating over. Also, your syntax for [].push is wrong. Commented May 29, 2013 at 17:24

2 Answers 2

3

Your .promise().done(...) isn't doing what you think it is. It's simply resolving instantly because there are no animations on the elements you are iterating over. Also, your syntax for [].push is wrong.

var defArr = $(categories).map(function(index, category_id) {
    return $.post('/modules/blog/add_post_categories', {post_id:result.result, category_id:$(category_id).val()});
}).get();

$.when.apply(null,defArr).done(function() {
    //var categories_names = [];
    //for (var i = 0; i < arguments.length; i++) {
    //    categories_names.push(arguments[i][0]);
    //}
    var categories_names = $.map(arguments,function(i,arr) {
        return arr[0];
    });
    var final_cats = categories_names.join("");
    console.info(final_cats);
});
Sign up to request clarification or add additional context in comments.

10 Comments

Wow. it would explain why it is all happening out of order as my comment above explained. Thanks for this. I shall try it now - I had no idea that the promise done was confined to animations though?
Even better, you don't need to manually push the results to the categories_names array. The promise of each $.post is resolved with an array of the form [ data, statusText, jqXHR ]. Thus, you can retrieve all category names from the promise results in the done callback using $.map(arguments, function(x) { return x[0] });.
@HelenDangerBurns $.promise() produces a promise for DOM element animations. AJAX requests themselves already implement promises, but you need to make sure that you keep those promises around when you want to bind to them! In your original code, there was nothing keeping track of those promises.
The latest edit makes it populate the array in the correct order
When you call .promise() on a jQuery collection, it works off of the "fx" queue. That's why your original code only tracked animations.
|
0
categories_names.push = result;

can you try changing this to

categories_names.push(result);

because push is a method, not a variable.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.