2016-03-07 73 views
0

我試圖從一個JSON源獲取特定數據段。我已經聲明瞭一個全局變量並嘗試更新全局變量,但它沒有正確更新。此外,我的調試警報運行順序令人困惑。混淆JavaScript的全局變量範圍和更新

<script> 

    //global variable 
    var latestDoorStatus = "initialized value"; //set value for debugging purposes 

    //debug alert which also calls the function 
    alert("Alert#1: call getDoorStatus = " + getDoorStatus("***********")); 

    function getDoorStatus(public_key) { 
    //get data in json form 
    var cloud_url = 'https://data.sparkfun.com/output/'; 
    // JSONP request 
    var jsonData = $.ajax({ 
     url: cloud_url + public_key + '.json', 
     data: {page: 1}, 
     dataType: 'jsonp', 
    }).done(function (results) { 
     var latest = results[0]; 

     //debug alert 
     alert("Alert #2: latestDoorStatus = " + latestDoorStatus); 

     //update the global variable 
     latestDoorStatus = latest.doorstatus; 

     //debug alert 
     alert("Alert #3: latestDoorStatus = " + latestDoorStatus); 

     //return the global variable 
     return latestDoorStatus; 

    }); 

    alert("Alert #4: latestDoorStatus = " + latestDoorStatus); 
    } 

</script> 

當我在瀏覽器中運行這個,我得到了以下行爲:

首先,我得到警報#4(應該在腳本運行結束)與全局變量的初始化值

然後我得到警報#1爲「不確定」。這應該是調用函數getDoorStatus的結果應該返回latestDoorStatus

的更新值

然後我得到警報#2 latestDoorStatus的初始化值,因爲全局變量尚未更新,這是有道理的

然後我得到警報#3的功能應該返回變量latestDoorStatus後警報#3(即在全局變量是否已正確更新),所以我不明白爲什麼警報#latestDoorStatus

的正確值1(這是應該有返回值)回來不確定,爲什麼警報#4這是應該在S的最後運行cript正在運行。

+0

你應該看看(http://stackoverflow.com/questions/14220321/how-do-i-return-the-a-an-asynchronous-call),我想你也有同樣的問題。 – Volune

回答

0

要調用$.ajax異步,並通過一個回調函數來done

function makeRequest() { 
    $.ajax({ // An async Ajax call. 
    url: cloud_url + public_key + '.json', 
    data: {page: 1}, 
    dataType: 'jsonp', 
    }).done(function (results) { 
    // this code is executed only after the request to cloud_url is finished. 
    console.log("I print second."); 
    }); 

    console.log("I print first."); 
} 

當請求完成的回調被調用,並完全取決於請求https://data.sparkfun.com/output/需要多長時間。所以,你的Ajax調用代碼之後,立即執行,我們不會等待HTTP請求來完成。

你的函數返回getDoorStatus沒什麼,但你的回調傳遞給done呢。你需要知道的事情是,你不能返回從異步執行的功能什麼。那麼,你可以返回,但沒有什麼可以使用返回的值。

所以相反,在回調傳遞到done的回調函數中,對https://data.sparkfun.com/output/的返回數據進行處理。

function getDoorStatus(public_key) { 
    //get data in json form 
    var cloud_url = 'https://data.sparkfun.com/output/'; 
    // JSONP request 
    var jsonData = $.ajax({ 
    url: cloud_url + public_key + '.json', 
    data: {page: 1}, 
    dataType: 'jsonp', 
    }).done(function (results) { 
    // latestDoorStatus = results[0]; // Not a good practice. 
    // Instead: 
    showDoorStatus(results[0]); 
    }); 
} 


function showDoorStatus(status) { 
    document.getElementById("door-status").innerText = status; 
    // Or something like this. 
} 

getDoorStatus("***********"); 

而且在某處你的HTML:我如何返回從一個異步調用的響應]

<p id="door-status"></p> 
+0

謝謝,這個建議奏效。我仍然不明白的是,我將「返回」放在您指定的區域//只有在對cloud_url的請求完成後才執行此代碼,以便在雲請求發生之前它不應該返回值完成,所以當我打電話getDoorStatus(「***********」));爲什麼它沒有給我一個有效的迴應(即使ajax調用是異步的,返回應該等待直到完成,Alert#1應該有好的數據)? – AGSTEIN

+0

您不能從您傳遞完成的回調函數中返回,因爲無法保證何時執行此函數;該函數在請求完成時執行,並且在那個時候,Ajax調用之後的大部分代碼可能已經被執行。您描述的行爲(或想要的行爲)僅適用於同步調用 - 即,執行將暫停,直到請求完成。 你的假設「即使ajax調用是異步的,返回應該一直等到完成,並且Alert#1應該有好的數據」 - 根本不適用。 – jeoj

+0

如果答案幫助你解決了問題,順便說一句,你可以接受答案:) – jeoj

0

.done()將在之後調用收到AJAX請求的響應!

1)getDoorStatus()從內部調用alert()頂部代碼=>#4顯示。這個函數在下面定義而不是在上面沒有關係。

2)alert()在代碼頂部被稱爲& getDoorStatus()確實直接返回與undefined所示的值=>#1

3)AJAX響應返回,.done()函數被調用=>#2#3被示出。