14

I'm having a bit of an issue with an error dealing with promises. So initially I had my function set up like this, and it all worked fine, no problems.

Original:

const request = require("request-promise");
async () => {
  const URL_HIDDEN = "...";

  let info = await request(URL_HIDDEN);
  info = JSON.parse(info).response.players[0];

  let playtime = await request(URL_HIDDEN);
  playtime = JSON.parse(playtime).response.games;

  console.log(info);
  console.log(playtime);
}

This is a shortened version, but basically I am just requesting information from the Steam API. Both the variables get print out with all the data no problem, but that changes once I do the refactor below.

Refactored:

const middleware = require("../middleware");
async () => {
  const URL_HIDDEN = "...";

  let requests = middleware.requestURI(URL_HIDDEN);
  console.log(requests);
}

and I started doing all the request handling in a separate function in a separate file.

const request = require("request-promise");
middlewareObj.requestURI = async (URL_HIDDEN) => {
  console.log("1");
  let info = await request(URL_HIDDEN);
  info = JSON.parse(info).response.players[0];

  console.log("2");

  let playtime = await request(URL_HIDDEN);
  playtime = JSON.parse(playtime).response.games;

  console.log("3");

  return [{ info }, { playtime }];
};

Once I got all the variables sorted out I want to return an array. However, once executed I get this printed to the console.

1
Promise { <pending> }
2
3

Any idea why it's printing promise pending once I refactored it?

In the original it prints out everything perfectly fine

Liam
  • 27,717
  • 28
  • 128
  • 190
Phil
  • 3,342
  • 5
  • 28
  • 50
  • so what the problem? – Ivan Aug 10 '17 at 08:41
  • 1
    Instead of logging what's actually in the array, it just prints out promise pending. There's a lot of information in each variable in the array – Phil Aug 10 '17 at 08:43
  • 1
    because `requestURI` is `async` and not completed when `console.log(requests)` executed – Ivan Aug 10 '17 at 08:51
  • 2
    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) – Liam Aug 10 '17 at 08:51
  • It's pretty much telling you what's going on, the promise is pending when your logging it. – Liam Aug 10 '17 at 08:53
  • 1
    Yep, I understand what its saying, but that's not the output I was looking for. In the original it prints out the data, in my refactored all I did was move it to a different function to handle the requests and then return an array of the data. I'm using await at each request, so I'm a little confused where it is going wrong. – Phil Aug 10 '17 at 08:56
  • 1
    in your "Refactored" code - did you miss an `await` in `let requests = middleware.requestURI(URL_HIDDEN);` - without an `await`, `requests` will be a pending promise – Jaromanda X Aug 10 '17 at 09:00
  • @JaromandaX make that an answer :D – robertklep Aug 10 '17 at 09:01
  • @robertklep - you never know if the code posted is relevant to the code that produces the output - could be a omission when typing the code here - I try not to post an answer prematurely :p – Jaromanda X Aug 10 '17 at 09:02
  • @JaromandaX true, but OP already commented on your (earlier, removed) comment that it solved their problem :) – robertklep Aug 10 '17 at 09:03
  • Yeah, I removed the comment because I was confused how all the code fit together :p posted a comment and and answer now :p – Jaromanda X Aug 10 '17 at 09:04

1 Answers1

24

in your "Refactored" code -

let requests = middleware.requestURI(URL_HIDDEN);

without an await, requests will be a pending promise - so, you need

let requests = await middleware.requestURI(URL_HIDDEN);

To expand on this. Any function tagged async will return a Promise.

async function foo() {
    return true;
}

calling this like

let bar = foo();
// here bar = pending promise of foo()

Results in bar being the Promise

calling it like

let bar = await foo(); 
// here bar == true

is sort of equivalent (but nowhere near equal) to

foo().then(bar => {
    // here bar == true
})

async/await can make code that is already simplified by Promise's even simpler - in this contrived example, it's not obvious though

Jaromanda X
  • 53,868
  • 5
  • 73
  • 87
  • I was not aware I had to state await on the function that is being called to handle the requests. Good to know – Phil Aug 10 '17 at 09:05
  • 1
    "To expand on this. Any function tagged async will return a Promise." This sentence saved my life (lol). I'm not sure about official documentation but I've never come across an explanation so simple for this. Makes total sense but I've never been told this before. – Matt Oct 23 '21 at 20:39
  • @Matt - it is [documented](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function#return_value) - but you're right, comparatively rarely mentioned – Jaromanda X Jul 14 '22 at 23:30