Search code examples
javascriptasync-awaitgeolocation

Geolocation.getCurrentPosition not assigning return value to variable via await


Context: building a basic weather app as a part of the Odin Project's full stack web development course.

What I'm trying to do: Get user location from built-in geolocation feature in browser to populate app with their local weather by default. I want to send the lat/lon data to loadApp() which will then use this data to automatically populate the webpage with their local weather

What happens instead: The function runs the if-statement and says the user denied access before the defaultLocation variable is even assigned.

What I tried: I tried making both async functions, as I thought async literally stopped the code from running until its promise was resolved, so I don't know how the alert(user denied access) line is ever running.

(I have no html/css built yet, just working from console right now.)


async function getLocationFromUser (){
    if ('geolocation' in navigator) {
        /* geolocation is available */
        console.log('geolocation IS available');
        navigator.geolocation.getCurrentPosition((position) => {
            console.log(position.coords.latitude, position.coords.longitude);
            let defaultCoords = [];
            defaultCoords.push(position.coords.latitude);
            defaultCoords.push(position.coords.longitude);
            defaultLocation =  defaultCoords;
          });
      } else {
        console.log('geolocation is NOT available');
        return false;
        /* geolocation IS NOT available */
    }
}



async function loadApp(){
    let defaultLocation = await getLocationFromUser();
    if(!defaultLocation){
        alert('user denied us');
        //code if user denies location service;
    } else {
        console.log(defaultLocation);
    }
}

loadApp().then(data => console.log(data)).catch(err => console.log(err));

Solution

  • Your getLocationFromUser doesn't return anything when geolocation is supported. Since getCurrentPosition uses a callback pattern, you could "promisify" the callback by wrapping it in a Promise. Return the promise immediately.

    No need to use async here as you're not awaiting anything in the function.

    function getLocationFromUser (){
      return new Promise((resolve, reject) => {
        if ('geolocation' in navigator) {
          navigator.geolocation.getCurrentPosition((position) => {
            resolve(position.coords);
          }, reject);
        } else {
          reject('Geolocation not supported');
        }
      });
    }
    
    async function loadApp(){
      try {
        const defaultLocation = await getLocationFromUser();
        console.log(defaultLocation);
      } catch (error) {
        alert('user denied us');
        //code if user denies location service;
      }
    }