与javascript全局变量作用域和更新混淆

与javascript全局变量作用域和更新混淆,javascript,jsonp,Javascript,Jsonp,我试图从json源中获取一段特定的数据。我声明了一个全局变量,并尝试更新该全局变量,但它没有正确更新。此外,调试警报的运行顺序令人困惑 <script> //global variable var latestDoorStatus = "initialized value"; //set value for debugging purposes //debug alert which also calls the function alert("Alert#1:

我试图从json源中获取一段特定的数据。我声明了一个全局变量,并尝试更新该全局变量,但它没有正确更新。此外,调试警报的运行顺序令人困惑

<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>

//全局变量
var latestDoorStatus=“初始化值”//为调试目的设置值
//也调用函数的调试警报
警报(“警报1:调用getDoorStatus=“+getDoorStatus”(“**********”));
功能GetDoor状态(公钥){
//获取json格式的数据
var cloud_url=https://data.sparkfun.com/output/';
//JSONP请求
var jsonData=$.ajax({
url:cloud_url+公钥+'.json',
数据:{page:1},
数据类型:“jsonp”,
}).完成(功能(结果){
var latest=结果[0];
//调试警报
警报(“警报#2:latestDoorStatus=“+latestDoorStatus”);
//更新全局变量
latestDoorStatus=最新的.doorstatus;
//调试警报
警报(“警报#3:latestDoorStatus=“+latestDoorStatus”);
//返回全局变量
返回最新状态;
});
警报(“警报#4:latestDoorStatus=“+latestDoorStatus”);
}
当我在浏览器中运行此操作时,会出现以下行为:

首先,我得到带有全局变量初始化值的警报#4(应该在脚本末尾运行)

然后我将警报#1设为“未定义”。这应该是调用函数getDoorStatus的结果,该函数应返回latestDoorStatus的更新值

然后我得到警报#2作为latestDoorStatus的初始化值,这是有意义的,因为全局变量尚未更新

然后,我得到警报#3,其值为latestDoorStatus

函数应该在警报#3之后返回变量latestDoorStatus(即,在正确更新全局变量之后),因此我不理解为什么警报#1(应该有返回值)返回时未定义,为什么应该在脚本末尾运行的alert#4首先运行。

.done()
将在收到AJAX请求的响应后调用

1)
getDoorStatus()
是从内部调用的
alert()
,显示在code=>4
的顶部。函数定义在下面而不是上面并不重要

2) 调用代码顶部的
alert()
,&
getDoorStatus()
直接返回一个值=>#1,显示为
未定义的


3) AJAX响应返回,
.done()
函数被调用=>#2#3显示。

您正在异步调用
$.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.");
}
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("***********");
在请求完成时调用回调,而何时调用完全取决于请求所需的时间。因此,Ajax调用后的代码会立即执行,我们不会等待http请求完成

函数
getDoorStatus
不返回任何内容,但传递给
done
的回调会返回任何内容。您需要知道的是,您不能从异步执行的函数返回任何内容。您可以返回,但是没有任何东西可以使用返回的值

因此,在传递给
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.");
}
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>


你应该看看,我想你也有同样的问题。谢谢,这个建议奏效了。我仍然不明白的是,我将“return”放在了您指示的区域中//此代码仅在对cloud\u url的请求完成后执行,因此在云请求完成之前它不应该返回值,所以当我调用getDoorStatus(“****************”)时;为什么它没有给我一个有效的响应(即,即使ajax调用是异步的,返回应该一直等到完成,并且警报#1应该有好的数据)?您不能从传递给done的回调函数返回,因为无法保证该函数何时执行;该函数在请求完成时执行,此时,Ajax调用后的大部分代码可能已经执行。您所描述(或想要的?)的行为只适用于同步调用——也就是说,执行将暂停,直到请求完成。您的假设“即使ajax调用是异步的,返回也应该等到完成并发出警报——1应该有好的数据”——根本不成立。如果答案帮助您解决了问题,您可以接受答案,顺便说一下:)