How to use Async Wait with HTML5 GeoLocation API?
Asked Answered
M

3

12

The first method returns promise.

getCoordinates() {
  return new Promise(function(resolve, reject) {
    navigator.geolocation.getCurrentPosition(resolve, reject);
  });
}

Returns the result of reverseGeoCode method.

async getAddress() {
  await this.getCoordinates().then(position => {
    let latitude = position.coords.latitude;
    let longitude = position.coords.longitude;
    let url = Constants.OSMAP_URL + latitude + "&lon=" + longitude;
    // Reverse geocoding using OpenStreetMap
    return this.reverseGeoCode(url);
  });
}

Uses custom class to make an API call and return the result.

reverseGeoCode(url) {
  let requestService = new RequestService("json", url);
  requestService.call().then(result => {
    return result;
  });
}

This is how I call:

let geoLocation = new GeoLocation();
geoLocation.getAddress().then(r => {
  console.log(r);
});

The console logs undefined.

Messmate answered 14/8, 2018 at 13:57 Comment(4)
getAddress has no return statement, so of course it returns a Promise that resolves as undefinedMonopolist
Your reverseGeoCode isn't returning anything, the return call is in the then() callback which isnt a return for the outer functionMarduk
@Monopolist return this.reverseGeoCode(url); this should be outside the await?Messmate
@PatrickEvans I cannot return value from inside the then to outside?Messmate
U
10

There are several problems with the shown snippets

  1. getAddress() doesn't actually return anything.

  2. If await is used, then() is not needed or vice-versa (blocking or non-blocking, not both).

Here is a correct version

async getAddress() {
  // notice, no then(), cause await would block and 
  // wait for the resolved result
  const position = await this.getCoordinates(); 
  let latitude = position.coords.latitude;
  let longitude = position.coords.longitude;
  let url = Constants.OSMAP_URL + latitude + "&lon=" + longitude;

  // Actually return a value
  return this.reverseGeoCode(url);  
}

You'll also have to rewrite reverseGeoCode in a similar fashion, something like

async reverseGeoCode(url) {
  let requestService = new RequestService("json", url);
  return await requestService.call();
}
Utica answered 14/8, 2018 at 14:4 Comment(3)
Thanks for the answer. I still get undefinedMessmate
Which is probably caused by ` return this.reverseGeoCode(url); `Messmate
Thank you for this answer, I'm more of a server side dev and my JS is still basic but I wanted to wait for the results of this before having the app proceed to try to map it onto a Google map. Thanks to your answer I was able to figure out how to make the app "Wait" first for the location before proceedingDroughty
H
13

The code below show similar issue. Try to refactor it. Remember to use it with await in async function. Something like:

window.onload = async () => {

const getCoords = async () => {
        const pos = await new Promise((resolve, reject) => {
          navigator.geolocation.getCurrentPosition(resolve, reject);
        });
    
        return {
          long: pos.coords.longitude,
          lat: pos.coords.latitude,
        };
    };

const coords = await getCoords();
}



 
Hooge answered 5/8, 2020 at 15:20 Comment(0)
U
10

There are several problems with the shown snippets

  1. getAddress() doesn't actually return anything.

  2. If await is used, then() is not needed or vice-versa (blocking or non-blocking, not both).

Here is a correct version

async getAddress() {
  // notice, no then(), cause await would block and 
  // wait for the resolved result
  const position = await this.getCoordinates(); 
  let latitude = position.coords.latitude;
  let longitude = position.coords.longitude;
  let url = Constants.OSMAP_URL + latitude + "&lon=" + longitude;

  // Actually return a value
  return this.reverseGeoCode(url);  
}

You'll also have to rewrite reverseGeoCode in a similar fashion, something like

async reverseGeoCode(url) {
  let requestService = new RequestService("json", url);
  return await requestService.call();
}
Utica answered 14/8, 2018 at 14:4 Comment(3)
Thanks for the answer. I still get undefinedMessmate
Which is probably caused by ` return this.reverseGeoCode(url); `Messmate
Thank you for this answer, I'm more of a server side dev and my JS is still basic but I wanted to wait for the results of this before having the app proceed to try to map it onto a Google map. Thanks to your answer I was able to figure out how to make the app "Wait" first for the location before proceedingDroughty
O
1

Here is a clean, simple version that encapsulates the API into a single function:

<!doctype html>

<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Geolocation API</title>
  <meta name="description" content="demo of the geolocation api">
  <meta name="author" content="Mark Tyers">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <script type="module" src="location.js" defer></script>
</head>

<body>
  <h1>GeoLocation</h1>
    <p></p>
    <p></p>
</body>
</html>

/* location.js */

try {
    const position = await getCurrentPosition()
    console.log(position)
    const lat = position.coords.latitude
    const lon = position.coords.longitude
    document.querySelector('p:nth-of-type(2)').innerText = `latitude: ${lat}`
    document.querySelector('p:nth-of-type(1)').innerText = `longitude: ${lon}`
} catch(err) {
    console.log(err)
    document.querySelector('p:nth-of-type(1)').innerText = err.message
}

function getCurrentPosition() {
    return new Promise( (resolve, reject) => {
        navigator.geolocation.getCurrentPosition(
            position => resolve(position),
            error => reject(error)
        )
    })
}
Oud answered 5/1, 2022 at 21:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.