2016-08-11 75 views
2

我正在執行AJAX調用以檢索處於特定狀態的所有商店。問題是,最後2行無法訪問我在get調用中返回函數中構建的任何可變內容。JavaScript變量卡在循環內 - 無法訪問

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 
    } 

我該怎麼做才能解決這個問題?我一直在嘗試奇怪的全局變量技巧和各種黑客攻擊,但沒有任何工作。

UPDATE 我也試圖把我的最後兩行$.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); 
     }) 
    } 

}); 
+2

這不是_stuck_循環,它關於時間。在數據從服務器加載並分配給變量之前,您正在訪問該變量。 **沒關係,但如何解決這個問題?**只需移動'$ .get()'回調中的最後一條語句即可。 – Tushar

+0

@Tushar請看我對我的問題的更新,爲什麼我想這樣做,但遇到了問題。 – qarthandso

+0

@qarthandso請參閱我的編輯以獲取適用於'Update 2'的工作解決方案。此外,我不知道爲什麼這被標記爲重複(特別是對於這個問題,因爲這不是你要求的,但這[先前被問到](http://stackoverflow.com/questions/7053965/when-使用回調 - 在一個循環在JavaScript的是在那裏任何方式來保存一個變種)其他地方,但重複沒有指向一個相關的問題。) –

回答

2

這是一個異步 $不用彷徨功能。也就是說,代碼執行將而不是在該行等待,直到完成$ .get,執行回調函數,然後繼續執行$ .get之後的下一行。實際上,它將執行對$ .get函數的異步調用,並立即繼續執行至console.log(fullHTML)行。目前還不能保證$ .get函數已經完成甚至開始,因爲它正在異步執行。

至於你的問題與j的可訪問性,這是一個問題,可以回到關閉。當您在$ .get回調內部訪問時,您的j變量將引用已經循環遍歷的j變量,並將返回不正確的j值,因爲您可能希望從$ .get請求獲得值爲j執行。因此,您需要在本地關閉中存儲j,方法是將其明確地聲明爲var current = j,而不是在$ .get回調中引用j,您將參考current,它將按預期執行。這不起作用!

編輯

我們可以強制創建一個新的範圍,如果我們聲明一個匿名函數並執行這方面的內部$不用彷徨。這不是一個漂亮的解決方案,但它的工作原理!

要修復您的代碼,請將您的呼叫放入$中。得到回調,像這樣:

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變量之前打破了線。

+0

我想這樣做,但也遇到了問題。請參閱我的更新問題,瞭解爲什麼這種方法不適合我。 – qarthandso

+0

@qarthandso更新了我的答案以解決該問題。 –

+0

這是確切的解決方案。非常感謝。爲什麼這個IIFE是必需的?存儲當前的「狀態」值? – qarthandso