【问题标题】:Global Javascript variable from AJAX JSON request来自 AJAX JSON 请求的全局 Javascript 变量
【发布时间】:2018-02-22 22:52:37
【问题描述】:

您好,我正在将此代码用于我的 AJAX JSON 请求,但对于某些人来说,如果我尝试将 jsonObj 设为全局变量,而 console.log() 在调试器控制台中始终显示为未定义

为了澄清我的问题,如何从 AJAX JSON 请求中检索全局变量

function loadJSON() {
  var data_file = "https://www.tutorialspoint.com/json/data.json";
  var http_request = new XMLHttpRequest();
  try {
    // Opera 8.0+, Firefox, Chrome, Safari
    http_request = new XMLHttpRequest();
  } catch (e) {
    // Internet Explorer Browsers
    try {
      http_request = new ActiveXObject("Msxml2.XMLHTTP");

    } catch (e) {

      try {
        http_request = new ActiveXObject("Microsoft.XMLHTTP");
      } catch (e) {
        // Something went wrong
        alert("Your browser broke!");
        return false;
      }

    }
  }

  http_request.onreadystatechange = function() {

    if (http_request.readyState == 4) {
      // Javascript function JSON.parse to parse JSON data
      var jsonObj = JSON.parse(http_request.responseText);

      // jsonObj variable now contains the data structure and can
      // be accessed as jsonObj.name and jsonObj.country.
      document.getElementById("Name").innerHTML = jsonObj.name;
      document.getElementById("Country").innerHTML = jsonObj.country;
    }
  }

  http_request.open("GET", data_file, true);
  http_request.send();
}
<h1>Cricketer Details</h1>

<table class="src">
  <tr>
    <th>Name</th>
    <th>Country</th>
  </tr>
  <tr>
    <td>
      <div id="Name">Sachin</div>
    </td>
    <td>
      <div id="Country">India</div>
    </td>
  </tr>
</table>

<div class="central">
  <button type="button" onclick="loadJSON()">Update Details </button>
</div>

【问题讨论】:

  • 使用您提供的代码似乎可以按预期工作 - see demo here。您能否更具体地说明为什么需要将 json 数据作为全局变量?
  • 我将您的代码更改为使用 https 并且它可以正常工作
  • 请查看我的answer,了解实现所需功能的正确方法。

标签: javascript html json ajax


【解决方案1】:

解决此问题的最佳方法是使用所谓的回调函数。回调函数是在特定事件发生时调用的函数。在您的情况下,该事件是从您的 JSON 端点 (URL) 检索的数据。

执行此操作的正确方法是创建一个函数,该函数将在接收到数据时调用,然后执行剩余的逻辑。如果您想让该数据也可以全局访问,部分回调函数可以更新您的全局变量。

在下面更新的代码中,我们首先声明了一个全局变量globalJSON,它保存了我们的data。在您收到任何数据之前(即在您单击按钮之前)globalJSON.data 的值将是null。接收到数据后,将使用接收到的数据调用回调函数updateView()。在updateView() 内部,我们更新全局变量globalJSON.data 并执行剩余的逻辑(即更新所需的HTML 元素)。

然后,您可以在代码中的任何其他位置使用globalJSON.data 来获取单击Update Details 按钮时收到的数据。

// declare your global variable that will get updated once we receive data

var globalJSON = {
    data: null
}

// this gets executed the moment you load the page - notice the value is null

console.log(globalJSON.data);

// this gets executed AFTER you receive data - notice call to updateView() inside AJAX call function

function updateView(data) {
    // this will update the value of our global variable
    
    globalJSON.data = data;
    
    // this is the rest of the logic that you want executed with the received data
    
    document.getElementById("Name").innerHTML = data.name;
    document.getElementById("Country").innerHTML = data.country;
    
    // this will show that the global variable was in fact updated
    
    console.log(globalJSON.data);
}

function loadJSON() {
    var data_file = "https://www.tutorialspoint.com/json/data.json";
    var http_request = new XMLHttpRequest();
    try {
        // Opera 8.0+, Firefox, Chrome, Safari
        http_request = new XMLHttpRequest();
    } catch (e) {
        // Internet Explorer Browsers
        try {
            http_request = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
            try {
                http_request = new ActiveXObject("Microsoft.XMLHTTP");
            } catch (e) {
                // Something went wrong
                alert("Your browser broke!");
                return false;
            }
        }
    }
    http_request.onreadystatechange = function() {
        if (http_request.readyState == 4) {
            // Javascript function JSON.parse to parse JSON data
            var jsonObj = JSON.parse(http_request.responseText);
            updateView(jsonObj);
            // jsonObj variable now contains the data structure and can
            // be accessed as jsonObj.name and jsonObj.country.
        }
    }
    http_request.open("GET", data_file, true);
    http_request.send();
}
 <h1>Cricketer Details</h1>
		
      <table class = "src">
         <tr><th>Name</th><th>Country</th></tr>
         <tr><td><div id = "Name">Sachin</div></td>
         <td><div id = "Country">India</div></td></tr>
      </table>

      <div class = "central">
         <button type = "button" onclick = "loadJSON()">Update Details </button>
      </div>

【讨论】:

    【解决方案2】:

    如果您只想从事件处理程序外部访问 jsonObj,请将其显式放置在全局范围内(无论这是否是一个好主意),您可以通过 window.jsonObj = JSON.parse(http_request.responseText); 在 window 上创建 jsonObj

    但您无法知道它何时在事件处理程序之外定义。但是,它将满足您能够console.log(window.jsonObj)(可能来自开发者控制台)的要求。如果您想查看值,也可以在事件处理程序中使用 console.log(jsonObj)。

    完整代码:

    <html>
    <head>
        <meta content = "text/html; charset = ISO-8859-1" http-equiv = "content-type">
    
        <script type = "application/javascript">
            function loadJSON(){
                var data_file = "http://www.tutorialspoint.com/json/data.json";
                var http_request = new XMLHttpRequest();
                try{
                // Opera 8.0+, Firefox, Chrome, Safari
                http_request = new XMLHttpRequest();
                }catch (e){
                // Internet Explorer Browsers
                try{
                    http_request = new ActiveXObject("Msxml2.XMLHTTP");
    
                }catch (e) {
    
                    try{
                        http_request = new ActiveXObject("Microsoft.XMLHTTP");
                    }catch (e){
                        // Something went wrong
                        alert("Your browser broke!");
                        return false;
                    }
    
                }
                }
    
                http_request.onreadystatechange = function(){
    
                if (http_request.readyState == 4  ){
                    // Javascript function JSON.parse to parse JSON data
                    // if you want to be able to access this property from the developer console
                    window.jsonObj = JSON.parse(http_request.responseText);
                    // if you just want to see the value
                    console.log(JSON.parse(http_request.responseText));
                    // jsonObj variable now contains the data structure and can
                    // be accessed as jsonObj.name and jsonObj.country.
                    document.getElementById("Name").innerHTML = jsonObj.name;
                    document.getElementById("Country").innerHTML = jsonObj.country;
                }
                }
    
                http_request.open("GET", data_file, true);
                http_request.send();
            }
    
        </script>
    
        <title>tutorialspoint.com JSON</title>
    </head>
    
    <body>
        <h1>Cricketer Details</h1>
    
        <table class = "src">
            <tr><th>Name</th><th>Country</th></tr>
            <tr><td><div id = "Name">Sachin</div></td>
            <td><div id = "Country">India</div></td></tr>
        </table>
    
        <div class = "central">
            <button type = "button" onclick = "loadJSON()">Update Details </button>
        </div>
    
    </body>
    

    【讨论】:

    • 这并没有太大变化,因为即使您可以设置全局变量的值,它也不会宣布其状态更改,因为 AJAX 调用是异步的。
    • Matt Newelski,我在回答中指出了这一点。我只是试图在不重构他的代码的情况下回答他的问题。谢谢!
    【解决方案3】:

    首先声明一个变量,如var jsonObj= '';(在你的函数内部。这个变量不是页面上下文的全局变量,而是函数上下文的全局变量)。访问函数中的变量。您使用http://www.tutorialspoint.com/json/data.json 但原始站点使用https 协议的网址存在问题。结果你得到了类似的错误

    阻止加载混合活动内容“http://www.tutorialspoint.com/json/data.json”

    所以也将网址更改为https://www.tutorialspoint.com/json/data.json。 然后你可以根据需要解析结果。

    <title>tutorialspoint.com JSON</title>
       
       <body>
          <h1>Cricketer Details</h1>
    		
          <table class = "src">
             <tr><th>Name</th><th>Country</th></tr>
             <tr><td><div id = "Name">Sachin</div></td>
             <td><div id = "Country">India</div></td></tr>
          </table>
    
          <div class = "central">
             <button type = "button" onclick = "loadJSON();">Update Details </button>
          </div>
    	  
    	  <script>
    	  function loadJSON(){
    	  var jsonObj= '';
                var data_file = "https://www.tutorialspoint.com/json/data.json";
                var http_request = new XMLHttpRequest();
                try{
                   // Opera 8.0+, Firefox, Chrome, Safari
                   http_request = new XMLHttpRequest();
                }catch (e){
                   // Internet Explorer Browsers
                   try{
                      http_request = new ActiveXObject("Msxml2.XMLHTTP");
    					
                   }catch (e) {
    				
                      try{
                         http_request = new ActiveXObject("Microsoft.XMLHTTP");
                      }catch (e){
                         // Something went wrong
                         alert("Your browser broke!");
                         return false;
                      }
    					
                   }
                }
    			
                http_request.onreadystatechange = function(){
    			
                   if (http_request.readyState == 4  ){
                      // Javascript function JSON.parse to parse JSON data
                      jsonObj = JSON.parse(http_request.responseText);
    
                      // jsonObj variable now contains the data structure and can
                      // be accessed as jsonObj.name and jsonObj.country.
    				  console.log(jsonObj);
                      document.getElementById("Name").innerHTML = jsonObj.name;
                      document.getElementById("Country").innerHTML = jsonObj.country;
                   }
                }
    			
                http_request.open("GET", data_file, true);
                http_request.send();
             }
    	  </script>
    		
       </body>

    【讨论】:

    • var jsonObj= ''; 位于 loadJSON() 声明内部这一事实不会使其成为全局,因为在您实际调用 loadJSON() 之前,jsonObj 不会存在
    • 是的@MattNewelski,你是对的。但从函数上下文来看,它可以被称为全局(因为你可以访问该函数中的变量)
    • 没有什么比将仅存在于函数局部范围内的变量称为全局变量更容易误导的了,尤其是对于初学者而言。
    • 编辑了我的答案。 @MattNewelski
    猜你喜欢
    • 2012-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-14
    • 1970-01-01
    • 2015-04-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多