AlGiorgio
AlGiorgio

Reputation: 497

Vue.js, Vuex vs. Promises

Imagine, I have a Vue app, required part of which structured like this:

enter image description here

I have three parts. Where:

1. Vue part:

<template>
<div>
    <div v-if="displayTable" class="dataTable">
        ...
    </div>
</div>
</template>

<script>
    export default {
        ...
        methods: {
            getDataset: function() {
                this.$store.dispatch('getDataFromDB')
                    .then(() => {
                        if (this.$store.state.dataSet.length > 0) {
                            this.displayTable = true
                        }
                    })
            }
        }
        ...
    }
</script>

2. Vuex part

const actions = {
    ...
    getDataFromDB ({commit}, payload) {
        DataSources.apiGetData(payload.querystring)
            .then(dataset => commit(GET_DATA, {dataset}))
    }
    ...
}

3. axios part

export const DataSources = {
    ...
    return apiGetData (queryString) {
        return axios.get('urlString').then(response => return response.data)
    }
    ...
}

Aim:

I need to retrieve and save data from DB in store's actions and only after that display div.dataTable. And that is Promise's functionality.

Problem:

In my case then()'s part processing first. What should I do to fix it?

Upvotes: 1

Views: 1125

Answers (2)

thanksd
thanksd

Reputation: 55664

The this.$store.dispatch() call returns a Promise by default, but because you aren't returning anything in the action being dispatched, the Promise resolves immediately and the then handler will execute before the async getDataFromDB action has finished.

You need to return the Promise created by the call to DataSources.apiGetData() in your getDataFromDB action:

getDataFromDB ({commit}, payload) {
  return DataSources.apiGetData(payload.querystring)
    .then(dataset => commit(GET_DATA, {dataset}))
}

This way, the Promise from the action is what is returned by the dispatch call, and the then handler won't fire until the async action has resolved.

Upvotes: 3

displaynamevalue
displaynamevalue

Reputation: 138

An alternative way to handle this would be to have displayTable as a computed value, avoiding any issues that may arise from async calls.

<template>
<div>
    <div v-if="displayTable" class="dataTable">
        ...
    </div>
</div>
</template>

<script>
    export default {
        ...
        computed: {
            displayTable() {
                return this.$store.state.dataSet.length > 0;
            },
        },
        methods: {
            getDataset: function() {
                this.$store.dispatch('getDataFromDB');
            }
        }
        ...
    }
</script>

Upvotes: 2

Related Questions