3

Hi i am using this code for my AJAX JSON request but for some if i try to make jsonObj a global variable and console.log() it always comes up as undefined in the debugger console

To clarify my question, how can I retrieve a global variable from an AJAX JSON request

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>
mplungjan
  • 169,008
  • 28
  • 173
  • 236
ben
  • 135
  • 1
  • 1
  • 8
  • Using the code you provided it seems to work as expected - [see demo here](http://jsbin.com/jaregoceju/edit?html,js,console,output). Can you be more specific about WHY you need the json data to be a global variable? – mnewelski Sep 14 '17 at 05:21
  • Likely a duplicate of https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call – mplungjan Sep 14 '17 at 05:33
  • I changed your code to use https and it worked as written – mplungjan Sep 14 '17 at 05:33
  • Please see my [answer](https://stackoverflow.com/a/46211375/1848744) for the right way of achieving the functionality you need. – mnewelski Sep 14 '17 at 05:43

3 Answers3

2

The best way to approach this is by using what's called a callback function. A callback function is a function that is invoked when specific event takes place. In your case that event is the data being retrieved from your JSON endpoint (URL).

The proper way to do this is to create a function that will be called when your data is received and will then carry out the remaining logic. If you want to make that data also accessible globally, part of the callback function can update your global variable.

In the updated code below we first declare a global variable globalJSON that holds our data. Before you receive any data (i.e. before you click the button) the value of globalJSON.data will be null. Once the data is received the callback function updateView() is called with the received data. Inside of updateView() we update the global variable globalJSON.data and carry out the remaining logic (i.e. updating the required HTML elements).

You can then use globalJSON.data anywhere else in your code to get the data received when Update Details button was clicked.

// 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>
mnewelski
  • 312
  • 1
  • 8
0

If you just want to access jsonObj from outside of the event handler, explicitly place it on the global scope (regardless of whether this is a good idea) you could create jsonObj on window by window.jsonObj = JSON.parse(http_request.responseText);

But you won't have any way of knowing when it's defined outside of the event handler. However, it would fulfill your requirement of being able to console.log(window.jsonObj) (presumably from the developer console). Also you could just console.log(jsonObj) in the eventhandler if you wanted to see the value.

full code:

<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>
Josh Bowling
  • 313
  • 3
  • 10
  • This doesn't change much as even though you can set the value of the global variable it will not announce its state changing because the AJAX call is asynchronous. – mnewelski Sep 14 '17 at 05:19
  • Matt Newelski, I made that point in my answer. I was merely attempting to answer his question without refactoring his code. Thanks! – Josh Bowling Sep 14 '17 at 14:19
0

Declare a variable at first like var jsonObj= ''; ( Inside your function. This variable is not global from the page context, but from the function context ). access the variable in your function. A problem in your url that you use http://www.tutorialspoint.com/json/data.json but the original site using https protocol. As a result you got an error something like that

Blocked loading mixed active content "http://www.tutorialspoint.com/json/data.json"

So change the url also to https://www.tutorialspoint.com/json/data.json. Then you can parse the result as you want.

<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>
Ataur Rahman Munna
  • 3,887
  • 1
  • 23
  • 34
  • The fact that `var jsonObj= '';` sits inside of the `loadJSON()` declaration does not make it global, since `jsonObj` won't exists until you actually call `loadJSON()` – mnewelski Sep 14 '17 at 05:23
  • Yes @MattNewelski, you are right. but from the function context, it's somehow can be called global (because you can access the variable within that function) – Ataur Rahman Munna Sep 14 '17 at 05:26
  • Nothing more misleading, especially for a beginner, than calling a variable that only exists in the functions local scope a global variable. – mnewelski Sep 14 '17 at 05:27
  • Edited my answer. @MattNewelski – Ataur Rahman Munna Sep 14 '17 at 05:30