Search code examples
javascriptjquerygoogle-geolocation

Can't pass var between functions in JS Codepen with Geolocations API


I am having trouble with passing a url variable between functions in my JS code on CodePen:

var options = {
  enableHighAccuracy: true,
  timeout: 5000,
  maximumAge: 0
};

function success(pos) {
  var crd = pos.coords;
  var lat = crd.latitude;
  var long = crd.longitude;
  var JSONurl = "https://maps.googleapis.com/maps/api/geocode/json?latlng=" + lat + "," + long + "&key=MY_APIKEY";

  console.log(JSONurl);
  console.log(`Latitude : ${crd.latitude}`);
  console.log(`Longitude: ${crd.longitude}`);
  return JSONurl;
 };

function error(err) {
  console.warn(`ERROR(${err.code}): ${err.message}`);
};

function getCity() {

  $.getJSON( JSONurl, function( json ) {
  var arr = $.map(json, function(el) { return el; })

  // console.log(Object.keys(arr[3]));
  console.log(arr[3]["address_components"][1]["long_name"]);

  }
)};


var JSONurl = navigator.geolocation.getCurrentPosition(success, error, options);             
getCity(JSONurl);

Ideally I would like to just call the getCity() function and for that function to call the success(pos) function and for that to initiate and return the JSONurl variable to getCity().

I have no idea why this doesn't work, but it's a bit hack-ey anyway so any suggestions for improvements welcome.


Solution

  • So there are a couple of issues:

    1. navigator.geolocation.getCurrentPosition(success, error, options) does not return a value. So "return JSONurl" will never work.
    2. key=MY_APIKEY should be your googleapis key (https://developers.google.com/maps/documentation/javascript/get-api-key, if not already)
    3. You need to use a promise because you don't know when the googleapis will return the info.
    4. You're probably going to have to use a callback function due to reason above.
    5. You need to take into account if the API denies the request.

    Working verison jsfiddle - will prompt for google api key

    (function(window){
    
      // Declare internal variables
      var _jsonURL = "";
      var _coords =  "";
      var _latitude =  "";
      var _longitude =  "";
    
      // Enter your google api key when prompted
      // https://developers.google.com/maps/documentation/javascript/get-api-key
      var APIKEY = prompt("Please enter your google API key ", ""); ; 
    
      // Create promise
      var _def = $.Deferred();
    
      window.GoogleAPI = {      
         options : {
                    enableHighAccuracy: true,
                    timeout: 5000,
                    maximumAge: 0
         },
         getGeolocation : function(){
                    // Set deferred action
                    _def = $.Deferred(navigator.geolocation.getCurrentPosition(success, error, GoogleAPI.options));
    
                    // allows chaining
                    return this;
         },
         getCity : function(callback){
            _def.done(function(){
                var city = "";
    
                $.getJSON( _jsonURL, function( json ) {
                   //check if access to the API was denied
                   if (json.status == "REQUEST_DENIED"){
                            console.error("API access denied.")
                            callback(null);
                            return;
                        };
    
                   var arr = $.map(json, function(el) { return el; })
    
                   city = arr[3]["address_components"][0]["long_name"];
                   console.log(city);
    
                   callback(city);
                })
                .fail(function(){
                   console.warn("failed to getCity");              
                   callback(null);
                }); //end getJSON          
             }); //end _def
    
             // allows chaining
             return this;
         } //end getCity
     }; //end window.GoogleAPI 
    
    
    
      function success(pos) {
         _coords = pos.coords;
         _latitude = _coords.latitude;
         _longitude = _coords.longitude;
         _jsonURL = "https://maps.googleapis.com/maps/api/geocode/json?latlng=" + _latitude  + "," + _longitude + "&key=" + APIKEY; 
    
         console.log(_jsonURL);
         console.log(`Latitude : ${_coords.latitude}`);
         console.log(`Longitude: ${_coords.longitude}`);
    
         // Tell the promise the deferred action has been completed
         _def.resolve();
      };
    
      function error(err) {
         console.warn(`ERROR(${err.code}): ${err.message}`);
    
         // Tell the promise the deferred action has failed
         _def.reject();
      };
    
    }(window))
    
    GoogleAPI.getGeolocation()
             .getCity(function(data){
                 if(data){
                    // do something with the data
                     alert(data);
                 }
             });
    

    Notes on Promises:

    Promises/deferred function is a heavy subject. Technically, $.getJSON is a promise that's assumed successful (although they included .fail() for error handling.)

    var _def = $.Deferred(navigator.geolocation.getCurrentPosition(success, error, GoogleAPI.options)); <-- create a deferred action (a promise.)
    

    Promises are async functions. Normally used when there is delay in getting data.

    _def.resolve(); <-- Says the promised action took place. 
    _def.reject(); <-- Says the promised action failed.
    _def.done(function(){}) <-- runs if promised action was successful. 
    _def.fail(function(){}) <-- runs id promised action failed.