30

I am making a loader for some components in my app.

Here is my component:

        mounted() {
            this.loading = true;

            this.getProduct();
        },
        methods: {
            async getProduct() {
                await this.$store.dispatch('product/getProducts', 'bestseller');

                console.log(123);

                this.loading = false;
            }
        },

Vuex action:

getProducts({commit}, type) {
        axios.get(`/api/products/${type}`)
            .then(res => {
                let products = res.data;
                commit('SET_PRODUCTS', {products, type})
            }).catch(err => {
            console.log(err);
        })
    },

The problem is in this line: await this.$store.dispatch('product/getProducts', 'bestseller');

I expect the code will stop at that line and wait for data is loaded from AJAX call and then set the loading is false;

But it isn't. The loading is still set false and the console.log run before my data is ready.

I already tried to move async/await into Vuex action and it worked. However, I didn't get the difference between them.

Below code is worked for me:

Component:

mounted() {
            this.loading = true;

            this.$store.dispatch('product/getProducts', 'bestseller').then((res) => {
                this.loading = false;
            });
        },

Vuex action:

async getProducts({commit}, type) {
        let res = await axios.get(`/api/products/${type}`);

        commit('SET_PRODUCTS', {products: res.data, type});
    }
user3118789
  • 589
  • 2
  • 12
  • 26

2 Answers2

41

Change this:

getProducts({commit}, type) {
    axios.get(`/api/products/${type}`)
        .then(res => {
            let products = res.data;
            commit('SET_PRODUCTS', {products, type})
        }).catch(err => {
        console.log(err);
    })
},

To this:

getProducts({commit}, type) {
    return axios.get(`/api/products/${type}`)
        .then(res => {
            let products = res.data;
            commit('SET_PRODUCTS', {products, type})
        }).catch(err => {
        console.log(err);
    })
},

Should work.

axios.get returns a promise. You would need to return that promise in order to let await wait for it. Otherwise, you are implicitly returning undefined and await undefined would immediately resolve.

jian
  • 1,236
  • 11
  • 11
6

You can not await a function without promise

await this.$store.dispatch('product/getProducts', 'bestseller');

This function return data or call new action

getProducts({commit}, type) {
    axios.get(`/api/products/${type}`)
        .then(res => {
            let products = res.data;
            commit('SET_PRODUCTS', {products, type})
        }).catch(err => {
        console.log(err);
    })
},

And this function return promise because of async function

async function return promise

async getProducts({commit}, type) {
    let res = await axios.get(`/api/products/${type}`);

    commit('SET_PRODUCTS', {products: res.data, type});

}

Now using above function now you can use

await this.$store.dispatch('product/getProducts', 'bestseller');

with await key word Or you can return axios because axios also return a promise.

Ashok
  • 2,846
  • 1
  • 12
  • 20