0

I'm getting my knickers in a twist about asynchronicity, promises and fetch requests I'm afraid.

I'm trying to get data from a fetch request, simple enough you'd think, but all I'm getting is "Promise {pending}" when I run it. I've read 10s of answers that seem very similar to mine but nothing seems to work.

When I console.log(data.formatted_address) within the final then(), I get the result just fine (after the pending Promise), but when I just return it, only "Promise {pending}" in the final console.log. Any help would be much appreciated!

const fetch = require('node-fetch');
const dotenv = require('dotenv');
dotenv.config();

function getCoordinates(address) {
  let searchAddress = address.split(" ").join("+");
  let url =
    "https://maps.googleapis.com/maps/api/geocode/json?address=" +
    searchAddress +
    "&key=" + process.env.GOOGLE_API;
  return fetch(url)
    .then(response => response.json())
    .then(data => data.results[0].formatted_address)
}

let a = getCoordinates("Buckingham Palace, London")

console.log(a)

EDIT:

Here's a much simpler version without API calls if you wanna try it at home!

function getCoordinates() {
  var promiseTest = new Promise(function(resolve, reject) {
    if (1 + 1 === 2) {
      resolve('pass')
    } else {
      reject('fail')
    }
  })
  return promiseTest.then(data => data);
}

console.log(getCoordinates())

Further EDIT:

So I think I'm thinking about Promises & Asynchronicity wrong. I need to do a little reading up about then. I'm going to stay away from using async functions and just extend my promises to include the callbacks. But thanks all for the help!

  • try `getCoordinates("Buckingham Palace, London").then(console.log);` – Krzysztof Krzeszewski Sep 20 '19 at 09:01
  • Just tried that... And this. getCoordinates("Buckingham Palace, London").then(data => console.log(data)) And they both give undefined I'm afraid! – Timothy Cole Sep 20 '19 at 09:04
  • @TimothyCole can you by any chance share the api key for testing your code, you can always delete this one and generate a new one.\ – Rohit Kashyap Sep 20 '19 at 09:13
  • 1
    if they give `undefined` then it seems that `data.results[0].formatted_address` is also undefined – Krzysztof Krzeszewski Sep 20 '19 at 09:22
  • Would rather not I'm afraid. It's definitely working though. When I use .then(data => console.log(data.results[0].formatted_address)) I get "Westminster, London SW1A 1AA, UK". I guess you could chuck anything in the promise. – Timothy Cole Sep 20 '19 at 09:22
  • are you sure you are returning the value from the last `.then` block? inside of the getCoordinates() function? it seems you've added quite a bit of code in there, perhaps it's just a problem of not returning the data – Krzysztof Krzeszewski Sep 20 '19 at 09:29
  • i see you've edited the answer, but the problem i pointed out of doing getCoordinates().then(console.log) still stands – Krzysztof Krzeszewski Sep 20 '19 at 09:31
  • Yeah I thought I was returning it. With the ES6 implicit return & returning the promise. I think that may well be where the route of the problem is. – Timothy Cole Sep 20 '19 at 09:34
  • This is just how promises work, or rather, how Javascript works. You want to synchronously return a result from an asynchronous process which would require code execution to be blocked until the asynchronous result is available. Since Javascript is single-threaded, blocking code execution would be severely bad. For this reason, you need to defer any code that relies on the result, which is what you do with `.then()`. – Lennholm Sep 20 '19 at 10:19

2 Answers2

0

Try this:

function getCoordinates(address) {
  let searchAddress = address.split(" ").join("+");
  let url =
    "https://maps.googleapis.com/maps/api/geocode/json?address=" +
    searchAddress +
    "&key=" + 'your key'
    return fetch(url);
}

getCoordinates('Buckingham Palace, London').then(res => res.json()).then(data => {
  console.log(data)
})
Rohit Kashyap
  • 1,553
  • 1
  • 10
  • 16
  • Yeah that works but it doesn't really let me do what I'm trying to do which is return a value from the promise. It's just passed the problem down to outside the getCoordinates function. – Timothy Cole Sep 20 '19 at 09:45
  • You can further do your work inside the then block? – Rohit Kashyap Sep 20 '19 at 09:46
  • 1
    @TimothyCole What you expect to be able to do isn't possible because of how Javascript is designed. You need to put everything that depends on that `data` inside the `.then()` callback. – Lennholm Sep 20 '19 at 10:22
0

If you want to get the result of a Promise as if it was a synchronous call you need to use async/await

The simplified example could be something like:

function getCoordinates() {
  var promiseTest = new Promise(function(resolve, reject) {
    if (1 + 1 === 2) {
      resolve('pass')
    } else {
      reject('fail')
    }
  })
  return promiseTest.then(data => data);
}

async function getAsyncData() {
    var data = await getCoordinates()
    console.log(data);
    return data;
}

getAsyncData()

NOTE: async/await does not work on Internet Explorer

filippo
  • 2,967
  • 1
  • 19
  • 19