1

I wrote a simple function in which your city location is determined. However, I am wondering if there is a way to force the function to wait for the getJSON and then move to the next line of code? In the example, you will see that it shows "Alert 1" skips "Alert 2" and goes directly to "Alert 3" and then shows the "Alert 2". Thank you in advance.

Best regards, George

var Alpha;

function Location(){
 alert(Alpha + " 1");
 $.getJSON("http://freegeoip.net/json/?callback=?", function(location){
  Alpha = location.city;
  alert(Alpha + " 2");
 }); 
 alert(Alpha + " 3");
}

$(document).ready(function() {
 Location();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
George Smith
  • 415
  • 8
  • 25

8 Answers8

8

In your code, getJSON returns the results asynchronously. This means that the code will keep running while the execution happens.

You can move your code to the success callback to make sure that nothing runs before the results are returned like so:

var Alpha;

function Location(){
    alert(Alpha + " 1");
    $.getJSON("http://freegeoip.net/json/?callback=?", function(location){
        Alpha = location.city;
        whenDone();
    }); 
}

function whenDone() {
    alert(Alpha + " 2");
    alert(Alpha + " 3");
}

$(document).ready(function() {
    Location();
});

In newer JavaScript versions, you can harness the the power of async/await and Promises to somehow "wait" for an execution:

let Alpha;

function Location() {
  return new Promise((resolve, reject) => {
    $.getJSON("http://freegeoip.net/json/?callback=?", location => {
      resolve(location);
    }); 
  }
}

async function init() {
  try {
    let location = await Location();
    Alpha = location.city;
  } catch(error) {
    console.error(error);
  }
}

$(document).ready(function() {
  init();
});

This will require that you polyfill some of the features.

Note: Newer versions of jQuery return a Promise compatible interface which you may use to await. I have not tried this, but wrapping the call in a Promise will work for older versions anyway.

Gorka Hernandez
  • 3,890
  • 23
  • 29
5

You can specify code to be run after the completion of $.getJson. Here is an example from the jQuery documentation.

var jqxhr = $.getJSON( "example.json", function() {
  console.log( "success" );
  })
  .done(function() {
    console.log( "second success" );
  })
  .fail(function() {
    console.log( "error" );
  })
  .always(function() {
    console.log( "complete" );
  });

jQuery Docs

aholtry
  • 2,723
  • 3
  • 24
  • 26
2

Put the logic you need to execute after the getJSON() call in the callback function, thats the function intention, like this:

var Alpha;
function ineedtorunmorecode(){
    alert(Alpha + " 4");
}

function Location(){
    alert(Alpha + " 1");
    $.getJSON("http://freegeoip.net/json/?callback=?", function(location){
        Alpha = location.city;
        alert(Alpha + " 2");
        alert(Alpha + " 3");
        ineedtorunmorecode();
    }); 
}

$(document).ready(function() {
    Location();
});
JC Hernández
  • 777
  • 3
  • 13
1

It is not possible to make the function that called getJSON wait. Doing this would be contrary to the model JavaScript uses for asynchronous events. Any code that is to execute upon completion of the call must be in (or called from) one of the callbacks. (Or you could use a promise API, which is all the same under the hood but better syntax...)

Mark Adelsberger
  • 42,148
  • 4
  • 35
  • 52
1

The function as it's asyncronous will not wait, but you can clean your code doing such an approach like this:

var Alpha;

function Location(){
 alert(Alpha + " 1");

   var onSuccess = function(location) {
                Alpha = location.city;
               alert(Alpha + " 2");
    }
 $.getJSON("http://freegeoip.net/json/?callback=?", onSuccess); 
  
        
}

$(document).ready(function() {
 Location();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Jordi Flores
  • 2,080
  • 10
  • 16
1

Unfortunately, in javascript there is not simple way to wait. You have to use callback functions.

1

Mentioned in the examples on the documentation, you can execute the code, when the $.getJSON is done. Here you can see the example. I added some console.log to show you how the code is executed.

(function() {
  console.log("Start Snippet");
  var flickerAPI = "http://api.flickr.com/services/feeds/photos_public.gne?jsoncallback=?";
  console.log("Start Load");
  $.getJSON( flickerAPI, {
    tags: "mount rainier",
    tagmode: "any",
    format: "json"
  })
    .done(function( data ) {
      console.log("End Load");
      $.each( data.items, function( i, item ) {
        $( "<img>" ).attr( "src", item.media.m ).appendTo( "#images" );
        if ( i === 3 ) {
          return false;
        }
      });
    });
  console.log("End Snippet");
})();
img {
  height: 100px;
  float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="images"></div>
DomeTune
  • 1,401
  • 10
  • 21
1

getJSON() is a shorthand Ajax function so, $.ajaxSetup({async : false}); will do the trick

user3665736
  • 101
  • 1
  • 6