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

时间:2016-03-07 07:43:00

标签: 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: 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(应该在脚本的END处运行)和全局变量的初始化值

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

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

然后我使用latestDoorStatus

的正确值获得警报#3

该函数应该返回变量latestDoorStatus AFTER alert#3(即全局变量正确更新后),所以我不明白为什么警报#1(应该有返回值)返回undefined以及为什么应该在脚本最末端运行的警报#4首先运行。

2 个答案:

答案 0 :(得分:0)

收到AJAX请求的响应后,

.done()将被称为

1)getDoorStatus()从代码顶部的alert()内部调用=&gt;显示#4 。函数定义如下,而不是上面定义无关紧要。

2)代码顶部的alert()被称为&amp; getDoorStatus() 直接返回值=&gt; #1 undefined一起显示。

3)返回AJAX响应,调用.done()函数=&gt; #2 #3 会显示。

答案 1 :(得分: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。您需要知道的是,您无法从异步执行的函数返回任何内容。好吧,你可以返回,但是没有任何东西可以使用返回的值。

相反,在回调中将https://data.sparkfun.com/output/中返回的数据做的事情传递给done

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>