1

I'm fetching text from a Dictionary API and I can't quite figure out why my code returns a pending promise. However logging the value returns the intended text. Here is my code,

const getWord = (difficulty) => {

    const fetchParameters = api + "?difficulty=" + difficulty

    let outputWord = fetchWord(fetchParameters).then(value => {
        console.log(value) // ->Logs intended text
        return value
    })

    return outputWord // -> Returns Pending Promise
}


async function fetchWord(fetchParams) {
        const response = await fetch(fetchParams)
        const text = await response.text()
        return text.split("\n")[1]
}

test = getWord(5)

console.log(test) // Results in Pending Promise

VLAZ
  • 26,331
  • 9
  • 49
  • 67
MBakir
  • 57
  • 5
  • Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Tyler Roper Oct 04 '19 at 00:56
  • `fetchWord` returns a promise since it is `async`, so the return value is unsurprising - note: there is no way to get a synchronous result from an asynchronous call. `async/await` provides the illusion of synchrony, but an `async` function always returns a promise, which by nature, the resolved value is obtained asynchronously – Bravo Oct 04 '19 at 01:11
  • noting that the text is logged in a `then` callback - and all promise callbacks are performed asynchronously, after the promise on which `then` (or `catch`) was called becomes settled. Because the callback being made later, the log of the pending promise appears before the log of the text. – traktor Oct 04 '19 at 01:25

1 Answers1

4

Since async functions return a Promise, you need to wait for that promise to resolve before you can use the value

One solution is to wrap your code in an async IIFE

(async () => {
  const getWord = (difficulty) => {

    const fetchParameters = api + "?difficulty=" + difficulty

    let outputWord = fetchWord(fetchParameters).then(value => {
      console.log(value) // ->Logs intended text
      return value
    })

    return outputWord // -> Returns Pending Promise
  }


  async function fetchWord(fetchParams) {
    const response = await fetch(fetchParams);
    const text = await response.text();
    return text.split("\n")[1]
  }

  let test = await getWord(5)
  console.log(test) // Results in correct output
})();

But note: test is still not going to be a value available outside this IIFE

Another solution is to use Promise.then

const getWord = (difficulty) => {

  const fetchParameters = api + "?difficulty=" + difficulty

  let outputWord = fetchWord(fetchParameters).then(value => {
    console.log(value) // ->Logs intended text
    return value
  })

  return outputWord // -> Returns Pending Promise
}


async function fetchWord(fetchParams) {
  const response = await fetch(fetchParams);
  const text = await response.text();
  return text.split("\n")[1]
}

getWord(5).then(test =>
  console.log(test)
);

But, again, value of test is still only available inside the final .then callback

There's just no way to have the result available "synchronously" since asynchronous code returns the value at some unknown time in the future - so you just have to work with asynchrony rather than try to short cut it

To me, it appears you are trying to use the intermediate async function to short circuit asynchrony - which you can't - the above code is over complicated way of doing

const getWord = async (difficulty) => {

  const fetchParameters = api + "?difficulty=" + difficulty;

  const response = await fetch(fetchParameters);
  const text = await response.text();
  return text.split("\n")[1];
};

getWord(5).then(test =>
  console.log(test)
);
Bravo
  • 6,022
  • 1
  • 10
  • 15