2016-03-07 100 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被示出。