0

I have a code similar to this:

$.ajax({
        success: function(data) {
            text = '';
            for (var i = 0; i< data.length; i++) {
                text = text + '<a href="#" id="Data_'+ i +'">' + data[i].Name + "</a><br />";
            }            
            $("#SomeId").html(text);

            for (var i = 0; i< data.length; i++) {
                $("#Data_"+i).click(function() {
                    alert(data[i]);
                    RunFunction(data[i]);
                    return false;
                });                
            }
        }
    });

This gets an array of some data in json format, then iterates through this array generating a link for each entry. Now I want to add a function for each link that will run a function that does something with this data. The problem is that the data seems to be unavailable after the ajax success function is called (although I thought that they behave like closures). What is the best way to use the queried json data later on? (I think setting it as a global variable would do the job, but I want to avoid that, mainly because this ajax request might be called multiple times)

Thanks.

3 Answers 3

1

Your problem is that the i variable is shared by the callbacks.

Therefore, all of the callbacks run on the last item.

The simplest solution is to use $.each:

$.each(data, function(i) {
  $("#Data_" + i).click(function() {
    alert(data[i]);
    RunFunction(data[i]);
    return false;
  });
});

This will make a separate function call for each iteration, so there will be a separate i variable (or, in this case, parameter) for each iteration.

Sign up to request clarification or add additional context in comments.

Comments

1

You can use .bind() directly and passing the data:

for (var i = 0; i< data.length; i++) {
    $("#Data_"+i).bind('click', {data: data[i]}, function() {
         alert(event.data.data);
          RunFunction(event.data.data);
          return false;
    });                
 }

I think you made a classical mistake, trying to generate functions in a loop. The variable i will have the same value for all functions but it is not even a valid array index anymore at the end of the loop.

See also JavaScript Closures for Dummies (no offense), example 5.

1 Comment

no offense taken. I was sure that closures didn't work as I expected I just didn't knew how to make them work.
0

SLaks answer is a good one, but he failed to explain why it wasn't working.

The problem is due to scoping. Try this out:

var logger = function(x){
  console.log(x);
};
for(var j = 0; j < 10; j++){
  window.setTimeout(function(){
    logger(j);
  }, 1000);
}

That nice little function prints out nothing but...9s! That's because the reference to j is kept by the timeout, so by the time the timeout runs, j is already set to 9.

Contrast that with:

var logger = function(x){
  console.log(x);
};
for(var j = 0; j < 10; j++){
  // we're wrapping our call in an anonymous function
  // don't do this in production code...make the function external instead
  // so you don't create 10 functions
  (function(k){
    window.setTimeout(function(){
      logger(k);
    }, 1000);
  })(j);
}

This version wraps the inner call in an anonymous function that takes as an argument the index. Since the scope of k is now limited to that function, the logger works as you'd expect.

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.