Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript doesn't seem to wait for return values

I've been struggling with this for a while now. I'm new to Javascript, and have been under the impression that the code I've been writing has been running asynchronously. Here is a generic example:

I run some code in function a. Function A then calls Function B, who needs to return a variable to A so A can use it in its later operations. It seems though that when A calls B, it still continues to run its own code, not waiting blocked for its return value, and B isn't fast enough such that A ends up reaching the point where it would have needed to use the return value and I get an undefined variable type error.

The way I have worked around this is have function A call Function B which then calls a Function C that would do what the later operations that A would be doing with the return value....I'm kind of serializing my code through calls instead of returns...that is cumbersome though...

Here is an example of when it happens in actual code:

function initialize() {     //Geocode Address to obtin Lat and Long coordinates for the starting point of our map     geocoder = new google.maps.Geocoder();     var results = geocode(geocoder);     makeMap(results[0].geometry.location.lat(), results[0].geometry.location.lng());  }  function geocode(geocoder) {     //do geocoding here...      var address = "3630 University Street, Montreal, QC, Canada";     geocoder.geocode({ 'address': address }, function (results, status) {         if (status == google.maps.GeocoderStatus.OK) {            return results;             }          else {             alert("Geocode was not successful for the following reason: " + status);         }    });  }  function makeMap(lat, long) {   //  alert(lat); for debuging     var mapOptions = {         center: new google.maps.LatLng(lat, long),         zoom: 17,         mapTypeId: google.maps.MapTypeId.ROADMAP     };      map = new google.maps.Map(document.getElementById("map_canvas"),         mapOptions); } 

Note: initialize gets called by body onload="initialize()" in my html.

So the issue is that the makeMap requires the lat and longitude values obtained by the Geocode function, but I get an error in the console saying results is undefined. What is going on? I came from Java so I'm a little confused about how data flow is happening here in JS! This will be valuable lessons for the future!

On a side question: How should I split my functions across external scripts? What is considered good practice? should all my functions be crammed into one external .js file or should I group like functions together?

like image 294
Georges Krinker Avatar asked Nov 19 '12 13:11

Georges Krinker


People also ask

How do I make a function wait before returning?

You can use the async/await syntax or call the . then() method on a promise to wait for it to resolve. Inside of functions marked with the async keyword, you can use await to wait for the promises to resolve before continuing to the next line of the function.

Does JavaScript have a wait function?

JavaScript may not have a sleep() or wait() function, but it is easy enough to create one using the built-in setTimeout() function — as long as you are careful with how you use it.


1 Answers

You seem to have a good understanding of the problem, but it sounds like you aren't familiar with the way to solve it. The most common way to address this is by using a callback. This is basically the async way to wait for a return value. Here's how you could use it in your case:

function initialize() {     //Geocode Address to obtin Lat and Long coordinates for the starting point of our map     geocoder = new google.maps.Geocoder();     geocode(geocoder, function(results) {         // This function gets called by the geocode function on success         makeMap(results[0].geometry.location.lat(), results[0].geometry.location.lng());             }); }  function geocode(geocoder, callback) {     //do geocoding here...      var address = "3630 University Street, Montreal, QC, Canada";     geocoder.geocode({ 'address': address }, function (results, status) {         if (status == google.maps.GeocoderStatus.OK) {             // Call the callback function instead of returning             callback(results);         } else {             alert("Geocode was not successful for the following reason: " + status);         }    });  }  ... 
like image 128
jncraton Avatar answered Sep 21 '22 16:09

jncraton