I'm doing an AJAX call to retrieve all stores in a certain state. The problem is, is that the last 2 lines can't access any of the variable content that I built up in the return function from the get
call.
var states = ['TX', 'AZ];
for(j = 0; j < states.length; j++) {
var fullHTML = '';
var full2;
$.get("//127.0.0.1:8000/api/state-stores/", {state: states[j]}, function(data) {
console.log(data.stores.length);
for(var i = 0; i < data.stores.length; i++) {
store_html = '' + data.stores[i].name + ' '
fullHTML += store_html;
}
})
// PROBLEM HERE
console.log(fullHTML); //empty
$("#" + states[j].toLowerCase() + "-table").html(fullHTML); //does nothing
}
What can I do to fix this? I've been trying weird global variable tricks and all sorts of hack-y things but nothing's working.
UPDATE
I also tried placing my last two lines inside the $.get
call but states[j]
is for some reason inaccessible inside the loop.
After debugging, it seems like just j
from the outer loop is inaccessible inside this return function. Is there a way to fix that?
UPDATE 2
I followed the advice given in the answer and I am getting properly concatenated strings for fullHTML
, but, each fullHTML
string is replacing only the last state in the table. It's as if the TX
tag is the only one receiving all the updates. I think this is closure-based but I don't know how to resolve this.
$(function() {
var states = ['AZ', 'CA', 'CO', 'GA', 'NV', 'NC', 'SC', 'TX'];
// var states = ['CA'];
for(var j = 0; j < states.length; j++) {
var current = j;
$.get("//127.0.0.1:8000/api/state-stores/", {state: states[j]}, function(data) {
var fullHTML = '';
for(var i = 0; i < data.stores.length; i++) {
store_html = '' + data.stores[i].name + ' ' + data.stores[i].address + '
' + data.stores[i].city + ' ' + data.stores[i].city + ' ' + data.stores[i].state + ' ' + data.stores[i].postal_code + ' '
fullHTML += store_html;
}
$('#' + states[current].toLowerCase() + '-table').html(fullHTML);
})
}
});
Answer
That is an asynchronous $.get function. That is to say, code execution will not wait at that line until the $.get is done, perform the callback function, and then continue onto the next line after the $.get. In reality, it will perform an asynchronous call to the $.get function, and continue execution immediately to the console.log(fullHTML)
line. There is no guarantee at this point that the $.get function has finished or even started, as it's being executed asynchronously.
As for your issue with the accessibility to j
, that's a problem that comes back to closures. Your j
variable, when accessed inside of the $.get callback, will reference the j
variable that has been looped through already, and will return the incorrect j
value, as you probably want the value of j
from when the $.get request was executed. So, you'll want to store j
inside of the local closure by declaring it explicitly like var current = j
, the instead of referencing j
inside of your $.get callback, you'd reference current
, and it would perform as intended. This doesn't work!
EDIT
We can force create a new scope if we declare an anonymous function and execute the $.get inside of that context. It's not a pretty solution, but it works!
To fix your code, put your calls inside of the $.get callback like so:
var states = ['TX', 'AZ'];
for(j = 0; j < states.length; j++) {
var fullHTML = '';
var full2;
(function() {
var current = j;
$.get("//127.0.0.1:8000/api/state-stores/", {state: states[j]}, function(data) {
console.log(data.stores.length);
for(var i = 0; i < data.stores.length; i++) {
store_html = '' + data.stores[i].name + ' '
fullHTML += store_html;
}
console.log(fullHTML); // not empty anymore
$("#" + states[current].toLowerCase() + "-table").html(fullHTML); //does stuff
});
})();
}
Now, your code will only perform the lines that were broken before AFTER it has populated the fullHTML
variable.
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment