Matt Brody
Matt Brody

Reputation: 1513

async await and promise chain is not waiting to resolve

I'm putting my API calls in a new function so I can easily call them with a couple of lines instead of a ton of code on every page. The problem I'm having is that the async and await is completing before returning the data.

I'm getting console.log(sess.getIdToken().getJwtToken()) consoled first, followed by undefined for console.log(getMessages), then the data from console.log(response).

So the await Auth.currentSession().then(...) runs but does't wait for the axios call inside of it. How do I return the data so I can access it in the useEffect?

useEffect(() => {
    async function getMessages() {
        const getMessages = await ApiService.getMessages();
        console.log(getMessages)
    }
    getMessages();
}, []);

async getMessages() {
    return await this.__sendRequest("/default/message", "GET");
}

async __sendRequest(url, method) {
    await Auth.currentSession().then(sess => {
        console.log(sess.getIdToken().getJwtToken())
        axios({
            method: method,
            url: process.env.REACT_APP_USER_URL + url,
            headers: {
                "X-TOKEN-ID": sess.getIdToken().getJwtToken(),
                "addresseeType": "P",
                "content-type": "application/json"
            }
        }).then(function (response) {
            console.log(response)
            return response
        }).catch(err => {
            console.error(err);
        })
    })
}

Upvotes: 0

Views: 1778

Answers (3)

Hendry
Hendry

Reputation: 900

Mixing async/await with promise-chaining (.then(...)) is a really easy way how to overcomplicate your code.

I can see a couple of places that contribute to this not working.

  • In __sendRequest you are not returning anything.
  • in the first .then you are lacking a return too.

Here is a simplified and fixed code

async __sendRequest(url, method) {
    const sess = await Auth.currentSession()

    console.log(sess.getIdToken().getJwtToken())
    
    const response = await axios({
        method: method,
        url: process.env.REACT_APP_USER_URL + url,
        headers: {
            "X-TOKEN-ID": sess.getIdToken().getJwtToken(),
            "addresseeType": "P",
            "content-type": "application/json"
        }
    })

    console.log(response)

    return response
}

Check the comments of the other answer, to understand about async/await, returning and call stack https://stackoverflow.com/a/69179763/1728166

Upvotes: 3

T.J. Crowder
T.J. Crowder

Reputation: 1074038

There are a couple of issues:

  1. __sendRequest has no return, so when it's done waiting it will fulfill its promise with undefined.
  2. The promise from the chain on Auth.currentSession() isn't waiting for the axios call to completely because the two chains aren't linked in any way.
  3. (Not the reason you're seeing the premature settlement, but still an issue.) Don't trap errors too early, let them propagate so the caller knows that something went wrong.

Also, in general, don't mix using .then/.catch with async/await, there's no need (generally); just use await:

useEffect(() => {
    async function getMessages() {
        try {
            const getMessages = await ApiService.getMessages();
            console.log(getMessages);
        } catch (error) {
            // ...*** handle/report error...
        }
    }
    getMessages();
}, []);

async getMessages() {
    return await this.__sendRequest("/default/message", "GET");
}

async __sendRequest(url, method) {
    const sess = await Auth.currentSession();
    console.log(sess.getIdToken().getJwtToken());
    return await axios({
        method: method,
        url: process.env.REACT_APP_USER_URL + url,
        headers: {
            "X-TOKEN-ID": sess.getIdToken().getJwtToken(),
            "addresseeType": "P",
            "content-type": "application/json"
        }
    });
}

Upvotes: 2

R...
R...

Reputation: 2570

getMessages() is async so you need to call with await and make the callback function of first line async so you can use await inside it.

  useEffect(async () => {
    async function getMessages() {
        const getMessages = await ApiService.getMessages();
        console.log(getMessages)
    }
    await getMessages();
 }, []);

you can simplify the __sendRequest by converting all then() callbacks into await and put the whole chain inside a try/catch block.

Upvotes: -1

Related Questions