我正在进行AJAX调用以检索某个州的所有商店。问题是,最后两行是否无法访问我在get
调用的return函数中构建的任何变量内容。
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 = '<tr><td>' + data.stores[i].name + '</td><td>'
fullHTML += store_html;
}
})
// PROBLEM HERE
console.log(fullHTML); //empty
$("#" + states[j].toLowerCase() + "-table").html(fullHTML); //does nothing
}
我该怎么做才能解决这个问题?我一直在尝试奇怪的全局变量技巧和各种各样的黑客行为,但没有任何工作。
更新
我还尝试将最后两行放在 $.get
调用中,但states[j]
由于某种原因在循环内无法访问。
调试之后,看起来外部循环中的j
在返回函数中是不可访问的。有办法解决这个问题吗?
更新2
我按照答案中给出的建议,我为fullHTML
,但获取正确连接的字符串,每个fullHTML
字符串正在替换只有表格中的最后状态。好像TX
标签是唯一接收所有更新的标签。我认为这是基于闭包的,但我不知道如何解决这个问题。
$(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 = '<tr><td>' + data.stores[i].name + '</td><td>' + data.stores[i].address + '<span class="small-table"><br>' + data.stores[i].city + '</span></td><td>' + data.stores[i].city + '</td><td>' + data.stores[i].state + '</td><td>' + data.stores[i].postal_code + '</td></tr>'
fullHTML += store_html;
}
$('#' + states[current].toLowerCase() + '-table').html(fullHTML);
})
}
});
答案 0 :(得分:2)
这是异步 $ .get函数。也就是说,代码执行将不在该行等待,直到$ .get完成,执行回调函数,然后继续到$ .get之后的下一行。实际上,它将对$ .get函数执行异步调用,并立即继续执行console.log(fullHTML)
行。此时无法保证$ .get函数已完成甚至启动,因为它是异步执行的。
至于您对 这不起作用! j
的可访问性的问题,这是一个回到闭包的问题。当您在$ .get回调中访问时,j
变量将引用已经循环的j
变量,并且将返回不正确的j
值,因为您可能需要从$ .get请求执行时j
的值。因此,您希望将j
存储在本地闭包中,方法是将其明确声明为var current = j
,而不是在$ .get回调中引用j
,您可以参考current
,它会按预期执行。
修改强>
如果我们声明一个匿名函数并在该上下文中执行$ .get,我们可以强制创建一个新的作用域。这不是一个漂亮的解决方案,但它确实有效!
要修复代码,请将调用放在$ .get回调中,如下所示:
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 = '<tr><td>' + data.stores[i].name + '</td><td>'
fullHTML += store_html;
}
console.log(fullHTML); // not empty anymore
$("#" + states[current].toLowerCase() + "-table").html(fullHTML); //does stuff
});
})();
}
现在,您的代码只会在填充fullHTML
变量之前执行已损坏的行。