Thursday, March 3, 2011

JavaScript Parent variables

I have the following code:

var address;
getAddress(0,0);
function getAddress(latlng) 
{
  if (latlng != null) 
  {
    geocoder.getLocations(latlng, 
    function(addresses) 
    {
      if(addresses.Status.code == 200) 
      { 
        address = addresses.Placemark[0].address.toString();
        alert(address);  // Outputs something :)
      }
    });
   }
   return address;   //returns nothing :(
}

I am very new to javascript and don't know why address always returns undefined but the alert does output something.

geocoder is an instance of google maps apis http://code.google.com/apis/maps/documentation/reference.html#GClientGeocoder

From stackoverflow
  • I think that your problems are all related to scope. Generally speaking, you don't want to rely on a global declaration of a variable to be used within the scope of a function.

    This should correct any scope issues with your function:

    var address = getAddress(0,0);
    
    function getAddress(latlng) {
        if (latlng != null) {
         var address = geocoder.getLocations(latlng, function(addresses) {
          if(addresses.Status.code == 200) { 
           return addresses.Placemark[0].address.toString();
          }
         });
        }
    return address;
    }
    
  • I can't see any reason why this won't work.

    To be doubley sure that nothing returning anything make the function call like this

    window.alert(getAddress(0,0));
    

    And then see what is being output

  • If I am not mistaken, it looks like

    geocoder.getLocations
    

    will not return a value, but expect a callback function, in your case:

    function(addresses) {
        if(addresses.Status.code == 200) { 
            return addresses.Placemark[0].address.toString();
        }
    }
    

    This "inner" return won't do much, as it will be returning to the insides of geocoder.getLocations.

    So, the function doing the assignment is probably being called later than the outer return (the callback and the 200 status suggest that there is a slow http call involved).

    That is,unless you can modify geocoder.getLocations the solution will be to make your function functional too, something like:

    function getAddress(latlng, callback) {
        if (latlng != null) {
            geocoder.getLocations(latlng, function(addresses){
                if(addresses.Status.code == 200) { 
                    address = addresses.Placemark[0].address.toString();
                    alert(address);
                    //Outputs something :)
                    callback(address);
                }
            });
        }
    

    }

    and you will call it with something like:

    getAddress(ll, function(address){
       alert(address);
    });
    

    And as a bonus you can get rid of the global variable :-)

    Victor : There is a lot of reading material on functional javascript: http://www.google.com/search?q=functional+javascript
  • I successfully reproduced the error by implementing geocoder.getLocations() to be asynchronous. If geocoder.getLocations() simply executed the parameter function then the change of the variable would become visible before getAddress() returns, so this is not a scope problem.

    var address;
    alert("B: address returned: " + getAddress());
    function getAddress() {
      executeFunction(function() {
        address = "myAddress";
        alert("C: address set to: " + address);
      });
      return address;
    }
    
    function executeFunction(aFunction) {
      alert("A: executing: " + aFunction);
      window.setTimeout(aFunction, 1);
    }
    

    Executing the code above results in the alert order A-B-C, meaning that address is returned before its assignment. Replacing window.setTimeout(aFunction, 1); with aFunction() results in the order A-C-B, the last alert being "B: address returned: myAddress".

0 comments:

Post a Comment