Search code examples
javascriptpromisees6-promise

How to fetch data from inner promise in javascript


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();

Solution

  • 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
    })