12

I am trying to get my head around async/await in NodeJS.

I have a function in a file as follows:

const getAccessToken = async () => {
  return new Promise((resolve, reject) => {

    const oauthOptions = {
      method: 'POST',
      url: oauthUrl,
      headers: {
        'Authorization': 'Basic ' + oauthToken
      },
      form: {
        grant_type: 'client_credentials'
      }
    };

    request(oauthOptions)
      .then((err, httpResponse, body) => {
        if (err) {
          return reject('ERROR : ' + err);
        }
        return resolve(body.access_token);
      })
      .catch((e) => {
        reject('getAccessToken ERROR : ' + e);
      });
  });
};

module.exports = getAccessToken;

This file is saved as twitter.js in a lib folder

In my index.js file I have the following:

const getAccessToken = require('./lib/twitter');

let accessToken;

try {
  accessToken = await getAccessToken();
} catch (e) {
  return console.log(e);
}

console.log(accessToken);

I get an error trying to run this code saying:

>   accessKey = await getAccessToken();
>                     ^^^^^^^^^^^^^^
> 
> SyntaxError: Unexpected identifier
>     at createScript (vm.js:74:10)
>     at Object.runInThisContext (vm.js:116:10)
>     at Module._compile (module.js:533:28)
>     at Object.Module._extensions..js (module.js:580:10)
>     at Module.load (module.js:503:32)
>     at tryModuleLoad (module.js:466:12)
>     at Function.Module._load (module.js:458:3)
>     at Function.Module.runMain (module.js:605:10)
>     at startup (bootstrap_node.js:158:16)
>     at bootstrap_node.js:575:3

Can I not await the required function as it is marked async ?

5
  • 1
    what nodejs version? Commented Jul 12, 2017 at 9:38
  • 1
    8.1.4 (running on Ubuntu) Commented Jul 12, 2017 at 9:41
  • 3
    the function getAccessToken = async () => shouldnt be async, and the peice of code accessKey = await getAccessToken(); should be inside an async function Commented Jul 12, 2017 at 9:46
  • 1
    if I add console.log(getAccessToken); below const getAccessToken = require('./lib/twitter').getAccessToken; it outputs [AsyncFunction: getAccessToken] which would suggest it is? Commented Jul 12, 2017 at 9:46
  • 1
    Ok I think I get what you say now. I'll do some investigation, but thanks for your help @Naeem Commented Jul 12, 2017 at 9:49

2 Answers 2

18

Your code is already correct. Without changing anything in twitter.js you have two options to use it:

  1. Functions marked with async always return promises. Therefore you can simply do:

    const getAccessToken = require('./lib/twitter');
    
    getAccessToken().then(accessToken => {
        console.log(accessToken);
    })
    
  2. All functions that return promises can be awaited upon but you cannot use await outside of an async marked functions. So you can also do:

    const getAccessToken = require('./lib/twitter');
    
    (async function () {
        var accessToken = await getAccessToken();
        console.log(accessToken);
    })();
    

The async/await keywords does not change how async functions behave. You still cannot wait on async functions synchronously, you can only do that inside an asynchronous function. Async/await is just a syntax sugar on top of promises.

Sign up to request clarification or add additional context in comments.

1 Comment

I was facing the same problem. I had a async function and at my index file, it was exported like that: module.exports = { importedAsync: require('./myAsyncFunction') } and finally, I imported it again from index.js in some different place. const { importedAsync } = require('./lib/index.js'). As result, I got: " importedAsync is not a function". In my case, it was solved by importing myFunction directly: const myAsyncFunction = require('./lib/myAsyncFunction.js'). It worked fine.
4

You are on the right track, however await can only be used inside an async function. So you have your structure backwards, and can be easily solved by changing a few things. However I suggest you overlook your code and make some structural changes. But here is a working version of your code:

const getAccessToken = () => {
  return new Promise((resolve, reject) => {

    const oauthOptions = {
      method: 'POST',
      url: oauthUrl,
      headers: {
        'Authorization': 'Basic ' + oauthToken
      },
      form: {
        grant_type: 'client_credentials'
      }
    };

    request(oauthOptions)
      .then((err, httpResponse, body) => {
        if (err) {
          return reject('ERROR : ' + err);
        }
        return resolve(body.access_token);
      })
      .catch((e) => {
        reject('getAccessToken ERROR : ' + e);
      });
  });
};

module.exports = getAccessToken;

And then:

const getAccessToken = require('./lib/twitter');

(async function() {
  try {
    let accessToken = await getAccessToken();
    console.log(accessToken);
  } catch (e) {
    return console.log(e);
  }
})()

This is a simple fix to your code to illustrate that you've got it backwards, and some structural changes are in order.

3 Comments

No need to use a promise here. The async keyword is a promise generator.
Thank you @Svenskunganka thats got it working. I appreciate your help
@Sven I have a similar use case. although I need to make my Token acessible to all other functions in my code. How can I do that? in this case If I am not mistaken I can only call the other functions after the access token. If I declared another async function in this file that would require the accessToken I would have to call it again and again. As many times as functions that would require it. Any ideia?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.