Jake Wilson
Jake Wilson

Reputation: 91213

Can't set scoped variable in $.post callback

I have the following type of structure:

(function(){

var objects = [];

$('button.one').on('click', function(){

  fetchObjects = function(objects) {
    $.post("/fetchObjects")
      .done(function(data){
        objects = data;
        console.log(objects.length);
      });
  }
  fetchObjects(objects)

});

$('button.two').on('click', function(){
  console.log(objects.length);
});

})();

You can see I have a variable objects that is local to this function. Initially its empty. When I click button.one I wish to populate objects with the returned value from some ajax request. It appears to work, however when clicking button.two, the objects variable is still an empty array.

Why isn't objects available in the jQuery callback?

I've also tried this approach but with the same results:

function callback(data) {
  facilities = data
}

$.post("/fetchObjects")
.done(function(data){
  callback(data);
});

What am I missing here? Please don't tell me to make "objects" global.

Upvotes: 0

Views: 46

Answers (2)

JJJ
JJJ

Reputation: 33153

Let's simplify the code a bit. You have essentially this:

var objects = [];

fetchObjects = function(innerObjects) {
  var data = ['a','b'];
  innerObjects = data;
  console.log(innerObjects.length);
};

fetchObjects(objects);
console.log(objects);

(I've changed the other objects variable's name just for clarity; the issue is the same even if it had the same name.)

When you call the function, innerObjects contains a reference to objects so modifying it would change the original array as well. But when you do

innerObjects = data;

now instead of modifying the array you're replacing the reference with something else. innerObjects "points" to data instead of objects and the original variable remains unchanged.

To make it work you'd need to loop through the data array (assuming it'll always be an array) and assign the contents to the objects reference one by one. This way you'll keep the original reference and modify the original array.

var objects = [];

fetchObjects = function(innerObjects) {
  var data = ['a','b'];
 
  for( var i = 0; i < data.length; i++ ) {
      innerObjects[i] = data[i];
  }
  console.log(innerObjects.length);
};

fetchObjects(objects);
console.log(objects);

Or, in your actual code:

(function(){

var objects = [];

$('button.one').on('click', function(){

  fetchObjects = function(objects) {
    $.post("/fetchObjects")
      .done(function(data){
        for( var i = 0; i < data.length; i++ ) {
          objects[i] = data[i];
        }
        console.log(objects.length);
      });
  }
  fetchObjects(objects)

});

$('button.two').on('click', function(){
  console.log(objects.length);
});

})();

Upvotes: 0

Chirag Mongia
Chirag Mongia

Reputation: 555

I don't know why you're passing objects as parameter. The following should work fine I think. Please let me know if you're trying to achieve something else.

(function(){

var objects = [];

$('button.one').on('click', function(){

  fetchObjects = function() {
    $.post("/fetchObjects")
      .done(function(data){
        objects = data;
        console.log(objects.length);
      });
  }
  fetchObjects()

});

$('button.two').on('click', function(){
  console.log(objects.length);
});

})();

Upvotes: 1

Related Questions