1

So basically this is the code to get users' location, after fetching the data from Promise I can't use it outside, I tried using push array object but can't use its value.

let addr = [];
var lati;
var long;

function getLocation() {
  if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(showPosition);
  } else { 
    console.log("Geolocation is not supported by this browser.");
  }
}

function showPosition(position) {
  lati = position.coords.latitude;
  long = position.coords.longitude;
  revgeo();
}

function revgeo(){
  const KEY = "api";
  const LAT = lati;
  const LNG = long;
  let url = `https://maps.googleapis.com/maps/api/geocode/json?latlng=${LAT},${LNG}&key=${KEY}`;

  fetch(url)
        .then(response => response.json())
        .then(data => {
          addr.push(data.results[0].formatted_address);
          console.log(data);
        })
        .catch(err => console.warn(err.message));
}


window.onload = getLocation();

console.log(addr); // this works
console.log(addr[0]); // this doesn't work
Przemek
  • 3,855
  • 2
  • 25
  • 33
  • What is the result when you console log addr? – Namit Piriya Mar 26 '21 at 18:41
  • Also see [is-chromes-javascript-console-lazy-about-evaluating-arrays](https://stackoverflow.com/questions/4057440/is-chromes-javascript-console-lazy-about-evaluating-arrays) for the logging behavior. – ASDFGerte Mar 26 '21 at 18:49

1 Answers1

2

The problem is that when you call the google API (ie your fetch operation) it will take a few milliseconds to complete. Your code below (outside of your fetch callback) executes before the fetch call has finished. Here is an example of what is happening.

let todo = null;
fetch('https://jsonplaceholder.typicode.com/todos/1')
  .then(response => response.json())
  .then(json => {
    todo = json;
    console.log('First Log', todo);
  })
  
  console.log('Second Log', todo);

Notice how the Second Log takes place before the First Log.

To fix this, you can simply move your logic so it takes place in your callback and therefore doesn't execute until the fetch call has finished. The other option is to use async/await

const getTodo = async (id) => fetch(`https://jsonplaceholder.typicode.com/todos/${id}`)
  .then(response => response.json())
  .catch( e => reject(e) );

const init = async () => {
  const todo = await getTodo(1);
  console.log(todo);
};

init();
mwilson
  • 12,295
  • 7
  • 55
  • 95
  • `fetch(...)` already returns a promise, so no need to use the promise constructor to wrap the `fetch()` call. See: [unnecessary use of promise constructor](https://blog.yousafkhan.me/common-promise-anti-patterns#unnecessary-use-of-promise-constructor) – Yousaf Mar 28 '21 at 11:23
  • I always forget that. – mwilson Mar 29 '21 at 15:09
  • Edited code will not work; you forgot to remove the `reject` function call in the callback function of the `catch` method. I suggest you remove the `catch` method call from the `getTodo` function and allow the `init` method to handle the error by adding the `try-catch` block around `await getTodo(1);` – Yousaf Mar 30 '21 at 16:08
  • It works fine. This is just an example for the OP to understand the basic issue. Feel free to provide your own answer. – mwilson Mar 30 '21 at 16:24