dace
dace

Reputation: 6363

Async function not returning finished promise

I have a javascript file where I'm grabbing a user's geolocation. I've wrapped it in a promise to make sure that it returns back coordinates.

geoLocation.js:

const getGeoLocation = () => {
  return new Promise(function(resolve, reject){
    function positionSuccess(position){             
      resolve(position);
    }
    function positionError(error){
      reject('ERROR: ' + error.code + ': ' + error.message);
    };
    navigator.geolocation.getCurrentPosition(positionSuccess, positionError);
  });
};

async function userCoords() {
  const response = await getGeoLocation();
}

module.exports = userCoords;

From here I'm importing the async userCoords function into a Main.js react component. In it's render method I'm asking it to console.log(userCoords()), but what I'm getting in the console is:

enter image description here

It looks like it's still waiting to finish with my getGeoLocation promise. What should I be doing to make sure that getGeoLocation is finished completely and that I can pass on it's return coordinates to my Main.js component?

Thank you!

Upvotes: 2

Views: 370

Answers (1)

Tamas Hegedus
Tamas Hegedus

Reputation: 29906

An async function will always return a promise, even if it is already settled. You must use promise.then or await. If you can make your render function async, then you can write:

console.log(await userCoords());

A function being async is poisonous, meaning that any function calling an async function (and expecting a settled value) must be itself async. This is particularry painful when programming user interface, because UI codes are inherently synchronuous. Showing data which comes from an asynchronouos datasource is hard to do well and demand careful engineering.

Maybe the simplest thing you can do is to poll the user coordinates independently from your render cycle:

var coords_promise = null;
var coords = null;

function render() {
    if (!coords_promise) {
        coords_promise = userCoords().then(function(newCoords) {
            coords = newCoords;
            coords_promise = null;
        });
    }
    console.log(coords);
}

setInterval(render, 20);

This piece of code will start fetching the coordinates at invocation to the render function. This means the first few cycles of the render function will print the initial value of the coords variable, but after then it will use the newest settled return value of userCoords(). This code also makes sure that no fetching is made if no call was made to the render() function, and no parallel invocations will be made to userCoords().

Upvotes: 2

Related Questions