与 javascript 全局变量范围和更新混淆

Confused with javascript global variable scope and update

我正在尝试从 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>

当我在浏览器中 运行 时,我得到以下行为:

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

然后我收到警报#1 "undefined"。这应该是调用函数 getDoorStatus 的结果,它应该 return latestDoorStatus

的更新值

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

然后我收到带有正确值 latestDoorStatus 的警报 #3

该函数应该 return 变量 latestDoorStatus 在警报 #3 之后(即在全局变量已正确更新之后)所以我不明白为什么警报 #1(应该有 returned 值)返回未定义,为什么 alert#4 应该在脚本的最后 运行 首先是 运行ning。

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

1) getDoorStatus() 在代码顶部的 alert() 内部被调用 => #4 所示。函数定义在下面而不是上面并不重要。

2) 代码顶部的 alert() 被调用 & getDoorStatus() 直接 而不是 return 一个值 => #1undefined 一起显示。

3) AJAX 响应 returned,调用 .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.");
}

回调在请求完成时调用,而何时完全取决于对https://data.sparkfun.com/output/的请求需要多长时间。所以 Ajax 调用后的代码会立即执行,我们不会等待 http 请求完成。

你的函数 getDoorStatus return 什么都没有,但是你传递给 done 的回调函数有。您需要知道的是,您不能 return 来自异步执行函数的任何内容。好吧,你 可以 return,但是那里没有任何东西可以使用 returned 值。

因此,在传递给 done.

的回调中,使用来自 https://data.sparkfun.com/output/ 的 returned 数据做您想做的事情
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>