Problem with async await in vue component - vue.js

I have strange situation, and I can't understand why in different location function works not the same.
I would like to retrieve data by axios. When I input my dispatch for axios in mounted hook - it works correct and I can write data from axios to draftData.
But, if I wrap my dispatch in function and locate in methods - data don't write in draftData.
Why it so? I wrote what was required of me (async/await).
Example.vue
<script>
import LineChart from "../LineChart";
export default {
components: { LineChart },
data: () => ({
loaded: false,
chartData: null,
labels:[],
datasets:[],
draftData:null,
}),
methods: {
loadIncomings(){
this.loaded = false
try {
let clubId = '5c3c5e12ba86198828baa4a7'
let dateFrom = '2021-06-01T00:00:00'
let dateTo = '2022-07-02T23:59:59'
let groupBy = 'month'
this.$store.dispatch('loadIncomings', {clubId, dateFrom, dateTo, groupBy})
console.log('loadIncomings---', this.$store.state.incomings)
this.draftData = this.$store.state.incomings
console.log('draftData---', this.draftData)
this.loaded = true
} catch (e) {
console.error(e)
}
},
calcIncomings() {
if (this.loaded){
for (let el of this.draftData ) {
console.log(el)
}
}
}
},
async mounted () {
await this.loadIncomings(),
await this.calcIncomings()
},
}
</script>
It looks like so:
"---UpdateIncomingsInfo---" - it is console.log from mutations (vuex). This work after axios.

Your loadIncomings function isn't async, so it doesn't return a Promise nor wait for your dispatch to be over.
Try like this:
async loadIncomings(){
this.loaded = false
let clubId = '5c3c5e12ba86198828baa4a7'
let dateFrom = '2021-06-01T00:00:00'
let dateTo = '2022-07-02T23:59:59'
let groupBy = 'month'
try {
await this.$store.dispatch('loadIncomings', {clubId, dateFrom, dateTo, groupBy})
this.draftData = this.$store.state.incomings
} catch (e) {
console.error(e)
} finally {
this.loaded = true
}
},
You can even return the data from your action directly (in addition to set the store from mutation):
this.draftData = await this.$store.dispatch('loadIncomings', {clubId, dateFrom, dateTo, groupBy})

Related

Hot to handle async props in vue 3 composition API

Parent compoment:
const { getGroup, removePubli, removeTablet, loadTotal, error } = useGroups();
const group = ref({});
getGroup(group_id).then((g) => {
group.value = g;
});
Child component:
const { group } = defineProps({
group: {
type: Object,
default: {},
},
});
Given the prop above, which is fetched by an async axios call, when I try to use it in a chield component it is undefined or a promise.
I've already tried to put an async inside onMounted hook but it doesn't work.
getGroup does it:
const getGroup = async (id) => {
const r = await api.get(`/api/v1/groups/${id}`);
if (r?.status !== 200) error.value = "Falhou";
return r.data;
};
I want to await it before the code continues or find a way to do something when the promise resolves itself.
I don't see in your code any await. Use await instead of .then!
<script setup>
const { getGroup, removePubli, removeTablet, loadTotal, error } = useGroups();
const group = ref({})
const result = await getGroup(someId)
group.value = result.data // or what ever
</script>

Nuxt - Wait after async action (this.$store.dispatch)

I'm new to Nuxt and I'm facing an issue that I don't understand.
If i code something like:
const resp1 = await this.$axios.$post('urlCall1', {...dataCall1});
this.$axios.$post('urlCall2', {...dataCall2, resp1.id});
The resp1.id is properly set in the 2nd axios call => we wait for the first call to be completed before doing the 2nd one.
However, when I define asyn actions in my vuex store ex:
async action1({ commit, dispatch }, data) {
try {
const respData1 = await this.$axios.$post('urlCall1', { ...data });
commit('MY_MUTATION1', respData1);
return respData1;
} catch (e) {
dispatch('reset');
}
},
async action2({ commit, dispatch }, data, id) {
try {
const respData2 = await this.$axios.$post('urlCall2', { ...data });
commit('MY_MUTATION2', respData2);
} catch (e) {
dispatch('reset');
}
}
and then in my vue component I fire those actions like:
const resp1 = await this.$store.dispatch('store1/action1', data1);
this.$store.dispatch('store2/action2', data2, resp1.id);
resp1.id is undefined in action2.
I also tried managing promise the "old way":
this.$store.dispatch('store1/action1', data1).then(resp1 => this.$store.dispatch('store2/action2', data2, resp1.id))
The result is still the same => id = undefined in action2
Can you guys please tell me where I'm wrong ?
Thanks in advance.
Last note: the 2 actions are in different stores
Vuex doesn't allow multiple arguments, so you have to pass it through as an object, so it could look like:
this.$store.dispatch('store2/action2', { ...data2, id: resp1.id });
And then in the store:
async action2({ commit, dispatch }, { id, ...data }) {
try {
const respData2 = await this.$axios.$post('urlCall2', { ...data });
commit('MY_MUTATION2', respData2);
} catch (e) {
dispatch('reset');
}
}

I'm getting this problem in vue trying to display a graphic with apexcharts?

I work with vue and apexchart. I call the api with the async method, to make sure that I am showing the correct information. I'm using console.Log and the array is correct. So does anyone know what is happening here? Thanks.
Probably your graph is created before the data of your api arrives. Try this :
data: () => ({
series: null
options: { ... }
}),
async mounted() {
this.loaded = false;
try {
const res = await fetch(urlYandex);
const json = await res.json()
this.series = json.data[0].metrics[0];
this.loaded = true;
} catch (e) {
console.error(e);
}
},
your apexchart you add like this :
<apexchart :options="options" :series="series" v-if="loaded"></apexchart>

How to use debounce with Vuex?

I am trying to debounce a method within a Vuex action that requires an external API.
// Vuex action:
async load ({ state, commit, dispatch }) {
const params = {
period: state.option.period,
from: state.option.from,
to: state.option.to
}
commit('SET_EVENTS_LOADING', true)
const res = loadDebounced.bind(this)
const data = await res(params)
console.log(data)
commit('SET_EVENTS', data.collection)
commit('SET_PAGINATION', data.pagination)
commit('SET_EVENTS_LOADING', false)
return data
}
// Debounced method
const loadDebounced = () => {
return debounce(async (params) => {
const { data } = await this.$axios.get('events', { params })
return data
}, 3000)
}
The output of the log is:
[Function] {
cancel: [Function]
}
It is not actually executing the debounced function, but returning to me another function.
I would like to present a custom debounce method which you can use in your vuex store as
let ongoingRequest = undefined;
const loadDebounced = () => {
clearTimeout(ongoingRequest);
ongoingRequest = setTimeout(_ => {
axios.get(<<your URL>>).then(({ data }) => data);
}, 3000);
}
This method first ensures to cancel any ongoing setTimeout in the pipeline and then executes it again.
This can be seen in action HERE

Why my vue js data member is not getting updated?

Data part
data () {
return {
containsAd: true
}
},
Method that manipulates the data member containsAd
updated () {
let _this = this
window.googletag.pubads().addEventListener('slotRenderEnded', function (event) {
if (event.slot.getSlotElementId() === 'div-gpt-ad-nativead1') {
_this.containsAd = !event.isEmpty // this is false
console.log('Ad Exists? ', _this.containsAd)
}
})
},
Just to check if the value has changed or not.
check () {
let _this = this
setTimeout(function () {
console.log('Current Value', _this.containsAd)
}, 5000)
}
Resulting Output
I think doing the event listener in the mounted hook will sort your issue.
data() {
return {
containsAd: true
};
},
mounted() {
window.googletag.pubads().addEventListener('slotRenderEnded', event => {
if (event.slot.getSlotElementId() === 'div-gpt-ad-nativead1') {
this.containsAd = ! event.isEmpty // this is false
console.log('Ad Exists?', this.containsAd);
}
});
}
Also using es6 shorthand function will avoid you having to set _this.