0

I am trying to fetch country name of user using HTML5 Geolocation API and Google Maps Geocoding API. I am using a custom modal to gracefully ask for the permissions. How can I access the returned country short name? Currently I am getting undefined.

function fetchCountry() {
  showCustomModal('To show data most relevant to you we need your location', {
    options: ['done', 'cancel']
  })
    .then(function(value) {
      if(value == 'cancel') return;

      navigator.geolocation.getCurrentPosition(function (position) {

        //if user agrees to share location info

        let latitude = position.coords.latitude;
        let longitude = position.coords.longitude;

        fetch(`https://maps.googleapis.com/maps/api/geocode/json?latlng=${latitude},${longitude}`)
          .then(response => response.json())
          .then(function (response) {

            //checking geocoding api response for errors
            if (response.status != 'OK' || !response.results[0]) return;

            for (let addressComponent of response.results[0].address_components) {
              if (addressComponent.types.includes('country'))
                return addressComponent.short_name; //returning country short name
            }

          });
      }, function () {
        //if does not gets the current position show error message
        //do something...
      });
    });
}

let country = fetchCountry();
SanyamMishra
  • 129
  • 10

1 Answers1

1

You could introduce a promise that is resolved when subseuqnet asynchronous requests are resolved (successfuly) or rejected (failed), as shown by the following

function fetchCountry() {

  // Add return statement here
  return showCustomModal('To show data most relevant to you we need your location', {
    options: ['done', 'cancel']
  })
    .then(function(value) {
      if(value == 'cancel') return;

      // Introduce the promise which will asynchronously process the post-modal request logic, and return a result on completion
      // or failure of that request
      return new Promise(function(resolve, reject) {

        navigator.geolocation.getCurrentPosition(function (position) {

          //if user agrees to share location info

          let latitude = position.coords.latitude;
          let longitude = position.coords.longitude;

          fetch(`https://maps.googleapis.com/maps/api/geocode/json?latlng=${latitude},${longitude}`)
            .then(response => response.json())
            .then(function (response) {

              //checking geocoding api response for errors
              if (response.status != 'OK' || !response.results[0]) {
                reject(); // Call reject to relay and failed request
              }

              for (let addressComponent of response.results[0].address_components) {
                if (addressComponent.types.includes('country'))
                  resolve(addressComponent.short_name); //returning country short name, via resolve
              }

            });
        }, function () {
          //if does not gets the current position show error message
          //do something...
          reject('Failed to get position') // Call reject to relay and failed request
        });
      })
    });
}

fetchCountry().then(function(country) {

  //access country here
}).catch(function(err) {

  //handle error here
})
Dacre Denny
  • 29,664
  • 5
  • 45
  • 65
  • This is not working as new promise is returned from inside `.then()` which itself is called asynchronously. Still getting `undefined`. – SanyamMishra Aug 23 '18 at 21:45
  • did you add the `return` statement before your `showCustomModal()` method? – Dacre Denny Aug 23 '18 at 21:47
  • This works now! can you explain why? – SanyamMishra Aug 23 '18 at 21:52
  • 1
    Great! Glad I could help - `showCustomModal()` returns a promise (as shown by the `.then()` handler after showCustomModal completes). Each time you call `.then()`, (ie add a handler) a promise object is returned. So by returning at the start of `fetchCountry` it causes the inner promise to be returned outside of `fetchCountry` which lets your external code add `.then()` or `.catch()` handlers as needed - hope that helps :-) – Dacre Denny Aug 23 '18 at 21:55
  • Thanks! I wish there exist some simple Promise chaining for this scenario. – SanyamMishra Aug 23 '18 at 22:00