Search code examples
javascripthtmlapigetjson

Javascript getJSON to store parameter as variable outside of function scope issue


Trying to return the date value from a URL via getJSON for the id='alert'. Seems like the getJSON is not working correctly even with async set to False. I took this code from another script that worked correctly.

<!DOCTYPE html>
<html>
<body>


<p><input type="text" id="input" value="100 | 47.6735" rows="30" cols="50"></p>

<button class="btn btn-primary btn-lg" onclick="getAlert()">Get Date Alert</button>

<p id="alert"></p>

<script>

$.ajaxSetup({
    async: false
  });

function getJSON_data(url){
  var date = '1'
  $.getJSON(
    url,
    function(data) {
    var date = data.date
    });  
  
  return {'test':date}
}

function getAlert() {

  var str = document.getElementById("input").value;;
  var res = str.split(" | ");
  var id = res[0];

  var url = 'http://date.jsontest.com/'
 
  var alert = getJSON_data(url).test;
  document.getElementById("alert").innerHTML = alert;
}

</script>

</body>
</html>

Added Async and Promises to the js portion of the script. Can't quite get the date to return in the "alert" portion.

...

function getJSON_data(url){
  return new Promise((resolve, reject) => {
    $.getJSON(
      url,
      function({date}) {
        resolve({test: date})
      });
    })
  })
}

function getAlert() {

  var str = document.getElementById("input").value;
  var res = str.split(" | ");
  var id = res[0];
 
  var url = 'http://date.jsontest.com/';

  var alert = (await getJSON_data(url)).test;
  document.getElementById("alert").innerHTML = alert
}

...

Solution

  • for first, please, never, absolutely never do not use syncronouse ajax, because one time, far far ago, asyncronouse requests was founded for reduce a lot of pain )

    for second, you should understand function scope and closure conception:

    var globalVar = "some value"
    
    function foo() {
      var varInClosure = "some other value"
      console.log(
        "here we have acces to global var:", globalVar, // some value
        "\nand local var:", varInScope // some other value
      ) 
    }
    
    console.log(
      "here we have access only to var in same scope", globalVar, // some value
      "\nbut not to var from other scope", varInScope // undefined
    )
    

    In you case, you can select one from to ways, ugly, but working, using global variables, or right and modern - using async/await and promises:

    function getJSON_data(url){
      return new Promise((resolve, reject) => {
        $.getJSON(
          url,
          function({date}) {
            resolve({test: date})
          });
        })
      })
    }
    
    //....
    
    var alert = (await getJSON_data(url)).test;
    document.getElementById("alert").innerHTML = alert;