Matt
Matt

Reputation: 2896

jQuery loop, only last ajax success executes

So this is the heart of my Chrome Extension [here], [jq is jQuery.noConflict()] the jq('.pam div .fbCurrentActionLink') returns each "Poke" link on Facebook. It uses .each() to loop through each person [aka, each person's "poke" link], and on success, it replaces the text "Poke" with a bold & green "Poked" text.

function execute()
{
        jq('.pam div .fbCurrentActionLink').each(function () {

        anc=jq(this)
        uid=anc.attr('ajaxify').match(/(\d+)/)[0]

        //ajax
                var post_form_id = jq('#post_form_id').val();
                var fb_dtsg = jq('input[name=fb_dtsg]').val();
                //use AJAX to submit poke, via their fb id
                jq.ajax({
                        type: 'POST',
                        url: 'ajax/poke.php?__a=1',
                        data: 'uid=' + uid + '&pokeback=1&post_form_id=' + post_form_id + '&fb_dtsg=' + fb_dtsg + '&post_form_id_source=AsyncRequest',
                        beforeSend: function(xhr){
                                xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=UTF-8");
                        },
                        success: function(data, textStatus){
                                anc.html('<b style="color:green !important">Poked</b>');
                        }
                });

        //ajax
        });

}

Now, the problem is, let's say there are 3 pokes to return. It will only execute the .html() on the last one. I can't figure out why.

Upvotes: 1

Views: 2197

Answers (2)

Cory Danielson
Cory Danielson

Reputation: 14501

I think the problem you're running into is that by the time the first ajax call is done, the value of anc has been overridden. Once the success event is triggered, anc is equal to it's value at the last iteration. To solve this, you must stop the values from being overridden or, during the loop, you must tie each ajax calls to the element where the results will be placed.

To tie an ajax call to a dom element, you need to supply define the context of the ajax call.

Give this a try, I'm hopeful it should work...

      jq.ajax({
              type: 'POST',
              context: this,        //added line
              url: 'ajax/poke.php?__a=1',
              data: 'uid=' + uid + '&pokeback=1&post_form_id=' + post_form_id + '&fb_dtsg=' + fb_dtsg + '&post_form_id_source=AsyncRequest',
              beforeSend: function(xhr){
                    xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=UTF-8");
              },
              success: function(data, textStatus){
                    $(this).html('<b style="color:green !important">Poked</b>');  
                    //changed to $(this) instead of anc
              }
      });

Upvotes: 5

Rob W
Rob W

Reputation: 349112

You have to prefix your variables by var. Otherwise, they're not locally (ie, in each) declared. If this is the case, the variable is overwritten at each iteration.

function execute() {
        jq('.pam div .fbCurrentActionLink').each(function () {
            var anc = jq(this);                              // Added `var`
            var uid = anc.attr('ajaxify').match(/(\d+)/)[0]; // Added `var`
            ....

Upvotes: 3

Related Questions