Wednesday, July 18, 2018

html - JavaScript Variable Stuck inside Loop - Can't Access



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.


No comments:

Post a Comment

plot explanation - Why did Peaches&#39; mom hang on the tree? - Movies &amp; TV

In the middle of the movie Ice Age: Continental Drift Peaches' mom asked Peaches to go to sleep. Then, she hung on the tree. This parti...