0

I'm using a class that is wrapping an API. It's utilizing Axios. In order to make requests to the API I require a JWT token that's retrieved via another request using an api key:

async setAuthorizationHeader() {
    const res = await this.Axios.post('/login', {
        api_key: ''
    });

    this.AuthToken = res.data.token
    this.Axios.defaults.headers.common['Authorization'] = `Bearer ${res.data.token}`
}

The class is instantiated once the script is loaded and setAuthorizationHeader method is run within the constructor, so it sends out a login request at the start. My problem is that if I want to run another API call on page load, I can't as I'll receive a 401 since we haven't gotten the token yet.

Here's another method within my class that I would also be running on page load:

async getPromotions() {
    const response = await this.Axios({
        method: 'POST',
        url: '/promotions',
        data: {
            ...this.baseData,
        }
    })

    return response.data
}

Is there any way to wait for the authorization step to complete before I run the getPromotions request?

Ryan Cady
  • 48
  • 4
  • Possible duplicate of [How and When to use \`async\` and \`await\`](https://stackoverflow.com/questions/14455293/how-and-when-to-use-async-and-await) – Greg2518 Sep 18 '18 at 21:50
  • So, `await setAuthorizationHeader(); await getPromotions()`? – Bergi Sep 18 '18 at 21:59
  • @Bergi when I use that I actually end up receiving "Can not use keyword 'await' outside an async function" – Ryan Cady Sep 18 '18 at 22:00
  • Please show us how and where you are running these functions. – Bergi Sep 19 '18 at 10:32
  • "*`setAuthorizationHeader` method is run within the constructor*" - [don't do that](https://stackoverflow.com/a/24686979/1048572) – Bergi Sep 19 '18 at 10:33
  • @Bergi hmm... I wasn't necessarily returning the promise from the constructor. I was just kicking the method off. I was thinking that I could set a authorizationPromise property on the class to the promise of this method. Does that sound okay? – Ryan Cady Sep 19 '18 at 13:31
  • @RyanCady Kicking the method off sounds just as bad - better pass the token to the constructor, and kick off the login request before instantiating the class. But yes, you could also store the authorisation promise on the instance, and `await` it in every method that needs to do an authorised request. – Bergi Sep 19 '18 at 13:53
  • That sounds like what I want to do, however when I'm in the method and I do something like `Class.authPromise.then((res) => { axioscall }` how would I return the promise from that call? Or am I backwards on this haha. I appreciate the help btw – Ryan Cady Sep 19 '18 at 14:10
  • @Bergi thank you for your help. I believe I've figured this out! – Ryan Cady Sep 19 '18 at 15:01
  • Yes, you'd either `return this.authPromise.then(() => this.axios(…)).then(res => res.data)` or just `await this.authPromise; const res = await this.axios(…); return res.data;` – Bergi Sep 19 '18 at 18:01

1 Answers1

1
  1. You can store promise that is about token's fetching as part of your API object.
  2. describe all your other API calls like API.tokenLoadingPromise.then(token => // making call with axios

This way you would ensure all your calls are executed only after token is retrieved.

skyboyer
  • 22,209
  • 7
  • 57
  • 64