1

I'm trying to understand how promises, callbacks etc work in node.js, particularly in the case of accessing the value outside of the function. I've spent time going through the answers here How do I return the response from an asynchronous call? and here call Stripe API with await but every variation I try I always end up with 'subscription' outside the function as undefined.

Thanks

let subscription;
async function getSub(){
    subscription = await stripe.subscriptions.retrieve('sub_HurxwcQoCIH7jv');
    // code here only executes _after_ the request is done?
    return subscription
}
getSub()
console.log("subscription: ", subscription) // subscription undefined??
quietplace
  • 471
  • 1
  • 4
  • 14

2 Answers2

4

There are 2 ways you can get a response

getSub()
.then(subscription => {
    console.log("subscription: ", subscription);
});

Or

const funcA = async() {
    const subscription  = await getSub();
    console.log("subscription: ", subscription);
}
funcA();
r7r
  • 1,440
  • 1
  • 11
  • 19
  • First function throw error "Uncaught SyntaxError: missing ) after argument list" - remove `;` after console.log`;` – Ezra Siton Aug 30 '20 at 06:40
  • Thanks. However, 'subscription' is still undefined outside of getSub() & functA. My aim is to 'export' the variable for use elsewhere in the parent scope eg. in the original position of my console.log() – quietplace Aug 30 '20 at 07:54
  • the async method returns promise, in order to resolve/reject it you must either chain it with then or use await keyword, for await keyword you again need an async method. If you want it to be available in global scope you will need to nest everything inside .then or inside the await method. – r7r Aug 30 '20 at 08:06
  • Ok. Thanks. At least I understand a bit more why it wasn't working. – quietplace Aug 30 '20 at 09:06
3

The code written after the async function is executes AFTER the sync function but getting done BEFORE the async function so it will be undefined as set in the first line let subscription // undefined

Lets cut it into pieces and number the chronology of happens:

1. let subscription;
2. async function getSub(){
    5. subscription = await stripe.subscriptions.retrieve('sub_HurxwcQoCIH7jv');
    // code here only executes _after_ the request is done?
    6. return subscription
}
3. getSub()
4. console.log("subscription: ", subscription) // subscription undefined??

So as you can see, the console log will happen BEFORE the assignment because 2. takes longer than 3. and 4. because of 5. in it.

You should do something like this:

(async () => {
  const sub = await stripe.subscriptions.retrieve('sub_HurxwcQoCIH7jv')
  console.log(sub) //
})()

You can also name the function:

const functionWithSomeName = async () => {
  const sub = await ...CODE HERE...
  console.log(sub)
}

functionWithSomeName()
Raz Buchnik
  • 7,753
  • 14
  • 53
  • 96
  • 1
    Thanks. I understand why it is happening, I'm just not sure how to make the variable available for use elsewhere in the parent scope eg. in the original position of my console.log(). In these functions 'subscription' will still be undefined outside of these functions. – quietplace Aug 30 '20 at 07:58
  • You should build the code so it will can access it the way I showed you. So your code should wrap this function from first of all. Your code should run in async function and execute this and then you can access it anywhere down. – Raz Buchnik Aug 30 '20 at 07:59
  • You also shouldn't return the value. – Raz Buchnik Aug 30 '20 at 08:03
  • Ok. Thanks. I'll have to rethink how to restructure my code. – quietplace Aug 30 '20 at 09:06