user14199346
user14199346

Reputation:

Axios returning pending promise

I have been searching for an answer for 3 days, so, I finally decided to ask by myself. I am using Nuxt JS and Riot API, and am new to both of them. I want to get data, then return it to store it inside another variable I could use later on. When I try to console log the data directly from inside my function, it works and I can see the data I want. But when I try to return it, it gives me this answer

returned console log

Here is my function

mounted() {
  console.log(this.fetchSomething())
},

methods: {
    async fetchSomething() {
        const test = await this.$axios.get('/api/')
        .then((res) => {
            return res.data;
        })
        console.log(test) // this works
        return test // this gives me a pending promise
        
    },
}

UPDATE

Thanks to jfriend00 for his amazing answer, correcting my code but most importantly explaining me what was wrong. I have now a better understanding of my mistake.

Corrected code

async mounted() {
  const gettest = await this.fetchSomething()
  console.log(gettest)
},

methods: {
  async fetchSomething() {
            const test = await this.$axios.get('/api/');
            //console.log(test.data);
            return test.data;            
        },
},

Upvotes: 1

Views: 4969

Answers (1)

jfriend00
jfriend00

Reputation: 707198

All async function return a promise. The return value inside the async function becomes the resolved value of that returned promise. If there is an await inside the async function, then the function returns a promise as soon as the interpreter encounters the first await in the function. If there are not await statements in the function, it still returns a promise that will be immediately resolved with whatever your return value is.

Keep in mind that await suspends internal execution of the async function. It does not stop the caller's execution. At that first await, the caller gets a pending promise and the caller keeps executing. The caller MUST use await or .then() themselves to get the return value from an async function.

Here's what happens inside your async function step-by-step"

  1. You call this.fetchSomething().
  2. As that starts to execute, the this.$axios.get('/api/') is executed and it returns a promise and then the interpreter processes the await thatPromise. At that first await, the function execution is suspended and the function immediately returns an unresolved and pending promise.
  3. Your console.log() sees that pending promise as the function has now returned
  4. Some time later, the axios.get().then(...) finishes and resolves the promise it returns so the await is done and assigned the resolved value of that axios.get().then() promise to your variable test. The value in test is the result of your return value in .then()
  5. Finally, you log the value of test and then you return the value of test.
  6. That return value becomes the resolved value of the promise that was already returned from the async function and that promise then gets resolved with that value.

If you look carefully at your two console.log() statements, you will see that this one console.log(this.fetchSomething()) happens first because that's where the function hit the await and then immediately returned the pending promise. Your second console.log(test) happens later after the await is done waiting for the axios promise.

FYI, many people prefer not to mix await and .then() (though this doesn't change the outcome you were asking about - it's just a style issue) and you could write your function like this:

methods: {
    async fetchSomething() {
        const test = await this.$axios.get('/api/');
        console.log(test.data);
        return test.data;            
    },
}

or, even this:

methods: {
    async fetchSomething() {
        const {data} = await this.$axios.get('/api/');
        console.log(data);
        return data;            
    },
}

Upvotes: 4

Related Questions