Async/Await not working for VueX getter but works for log
up vote
0
down vote
favorite
I have an object of convos with userIDs that I need to loop through and, inside the loop, I need to make a call to Firebase to get the corresponding userName and then return an object with the convos, userNames, and userIDs.
I have tried using the async/await and the result I get from console.log is correct but my return statement directly after that, is undefined. Why is this happening? They are receiving the same object.
store.js getter snippet
getConvosObj: state => {
var convoObj = {};
var userConvos = state.userProfile.convos;
async function asyncFunction() {
for (const key in userConvos) {
if (userConvos.hasOwnProperty(key)) {
const userID = userConvos[key];
var userName;
await fire.database().ref('/users/' + userID + '/userName').once('value', async (snapshot) => {
userName = await snapshot.val();
convoObj[key] = {userName, userID}
})
}
}
console.log(convoObj); //result: correct object
return convoObj; //result: undefined
}
asyncFunction();
}
javascript firebase vue.js async-await vuex
add a comment |
up vote
0
down vote
favorite
I have an object of convos with userIDs that I need to loop through and, inside the loop, I need to make a call to Firebase to get the corresponding userName and then return an object with the convos, userNames, and userIDs.
I have tried using the async/await and the result I get from console.log is correct but my return statement directly after that, is undefined. Why is this happening? They are receiving the same object.
store.js getter snippet
getConvosObj: state => {
var convoObj = {};
var userConvos = state.userProfile.convos;
async function asyncFunction() {
for (const key in userConvos) {
if (userConvos.hasOwnProperty(key)) {
const userID = userConvos[key];
var userName;
await fire.database().ref('/users/' + userID + '/userName').once('value', async (snapshot) => {
userName = await snapshot.val();
convoObj[key] = {userName, userID}
})
}
}
console.log(convoObj); //result: correct object
return convoObj; //result: undefined
}
asyncFunction();
}
javascript firebase vue.js async-await vuex
2
How do you know your function returnundefined
?
– ittus
Nov 9 at 5:42
I assume you think thatgetConvosObj
will returnconvoObj
? Because it doesn't return anything.
– robertklep
Nov 9 at 6:52
1
By design, getters are not meant to be asynchronous. As instead, they should return a certain store state and will be reactively updated when state changes. The fact, that code example above is quite hard to predict only proves that concept. Such approach also has performance flaws. Please, try to stick with original idea: calling actions -> changing state with mutations -> returning state with getters. This way flow is clear and debuggable.
– aBiscuit
Nov 9 at 6:54
Yes, I was trying to user thegetConvosObj
to returnconvoObj
. I'm fairly new to Vue so I didn't remember that I shouldn't do asynchronous stuff in getters. I've restructured it the way sosmii suggested below and it works now. Thanks everyone!
– MrSpinn
Nov 9 at 16:35
add a comment |
up vote
0
down vote
favorite
up vote
0
down vote
favorite
I have an object of convos with userIDs that I need to loop through and, inside the loop, I need to make a call to Firebase to get the corresponding userName and then return an object with the convos, userNames, and userIDs.
I have tried using the async/await and the result I get from console.log is correct but my return statement directly after that, is undefined. Why is this happening? They are receiving the same object.
store.js getter snippet
getConvosObj: state => {
var convoObj = {};
var userConvos = state.userProfile.convos;
async function asyncFunction() {
for (const key in userConvos) {
if (userConvos.hasOwnProperty(key)) {
const userID = userConvos[key];
var userName;
await fire.database().ref('/users/' + userID + '/userName').once('value', async (snapshot) => {
userName = await snapshot.val();
convoObj[key] = {userName, userID}
})
}
}
console.log(convoObj); //result: correct object
return convoObj; //result: undefined
}
asyncFunction();
}
javascript firebase vue.js async-await vuex
I have an object of convos with userIDs that I need to loop through and, inside the loop, I need to make a call to Firebase to get the corresponding userName and then return an object with the convos, userNames, and userIDs.
I have tried using the async/await and the result I get from console.log is correct but my return statement directly after that, is undefined. Why is this happening? They are receiving the same object.
store.js getter snippet
getConvosObj: state => {
var convoObj = {};
var userConvos = state.userProfile.convos;
async function asyncFunction() {
for (const key in userConvos) {
if (userConvos.hasOwnProperty(key)) {
const userID = userConvos[key];
var userName;
await fire.database().ref('/users/' + userID + '/userName').once('value', async (snapshot) => {
userName = await snapshot.val();
convoObj[key] = {userName, userID}
})
}
}
console.log(convoObj); //result: correct object
return convoObj; //result: undefined
}
asyncFunction();
}
javascript firebase vue.js async-await vuex
javascript firebase vue.js async-await vuex
edited Nov 9 at 5:36
asked Nov 9 at 5:21
MrSpinn
85
85
2
How do you know your function returnundefined
?
– ittus
Nov 9 at 5:42
I assume you think thatgetConvosObj
will returnconvoObj
? Because it doesn't return anything.
– robertklep
Nov 9 at 6:52
1
By design, getters are not meant to be asynchronous. As instead, they should return a certain store state and will be reactively updated when state changes. The fact, that code example above is quite hard to predict only proves that concept. Such approach also has performance flaws. Please, try to stick with original idea: calling actions -> changing state with mutations -> returning state with getters. This way flow is clear and debuggable.
– aBiscuit
Nov 9 at 6:54
Yes, I was trying to user thegetConvosObj
to returnconvoObj
. I'm fairly new to Vue so I didn't remember that I shouldn't do asynchronous stuff in getters. I've restructured it the way sosmii suggested below and it works now. Thanks everyone!
– MrSpinn
Nov 9 at 16:35
add a comment |
2
How do you know your function returnundefined
?
– ittus
Nov 9 at 5:42
I assume you think thatgetConvosObj
will returnconvoObj
? Because it doesn't return anything.
– robertklep
Nov 9 at 6:52
1
By design, getters are not meant to be asynchronous. As instead, they should return a certain store state and will be reactively updated when state changes. The fact, that code example above is quite hard to predict only proves that concept. Such approach also has performance flaws. Please, try to stick with original idea: calling actions -> changing state with mutations -> returning state with getters. This way flow is clear and debuggable.
– aBiscuit
Nov 9 at 6:54
Yes, I was trying to user thegetConvosObj
to returnconvoObj
. I'm fairly new to Vue so I didn't remember that I shouldn't do asynchronous stuff in getters. I've restructured it the way sosmii suggested below and it works now. Thanks everyone!
– MrSpinn
Nov 9 at 16:35
2
2
How do you know your function return
undefined
?– ittus
Nov 9 at 5:42
How do you know your function return
undefined
?– ittus
Nov 9 at 5:42
I assume you think that
getConvosObj
will return convoObj
? Because it doesn't return anything.– robertklep
Nov 9 at 6:52
I assume you think that
getConvosObj
will return convoObj
? Because it doesn't return anything.– robertklep
Nov 9 at 6:52
1
1
By design, getters are not meant to be asynchronous. As instead, they should return a certain store state and will be reactively updated when state changes. The fact, that code example above is quite hard to predict only proves that concept. Such approach also has performance flaws. Please, try to stick with original idea: calling actions -> changing state with mutations -> returning state with getters. This way flow is clear and debuggable.
– aBiscuit
Nov 9 at 6:54
By design, getters are not meant to be asynchronous. As instead, they should return a certain store state and will be reactively updated when state changes. The fact, that code example above is quite hard to predict only proves that concept. Such approach also has performance flaws. Please, try to stick with original idea: calling actions -> changing state with mutations -> returning state with getters. This way flow is clear and debuggable.
– aBiscuit
Nov 9 at 6:54
Yes, I was trying to user the
getConvosObj
to return convoObj
. I'm fairly new to Vue so I didn't remember that I shouldn't do asynchronous stuff in getters. I've restructured it the way sosmii suggested below and it works now. Thanks everyone!– MrSpinn
Nov 9 at 16:35
Yes, I was trying to user the
getConvosObj
to return convoObj
. I'm fairly new to Vue so I didn't remember that I shouldn't do asynchronous stuff in getters. I've restructured it the way sosmii suggested below and it works now. Thanks everyone!– MrSpinn
Nov 9 at 16:35
add a comment |
1 Answer
1
active
oldest
votes
up vote
-1
down vote
accepted
Why is this happening ?
Because you called async function synchronously.
lets make your code simpler.
getConvosObj: state => {
async function asyncFunction() {
// ...
}
asyncFunction();
}
at this point, your getConvosObj()
will return nothing, because getConvosObj()
ends before asyncFunction()
ends.
you need to wait until your asyncFunction()
ends, then your code should be like this:
getConvosObj: async state => { // <- changed here
async function asyncFunction() {
// ...
}
await asyncFunction(); // <- changed here too
}
but you should not do like this, because getters are not meant to be asynchronous by design.
this may work, but you should try a different approach.
So what should you do ?
Use actions before using getters
this is a basic approach.
async functions should be in actions.
so your store should be like this:
export default () =>
new Vuex.Store({
state: {
convoObj: null
},
mutations: {
updateConvoObj(state, payload) {
state.convoObj = payload;
}
},
actions: {
async fetchAndUpdateConvoObj({ state, commit }) {
const fetchUserData = async userId => {
const snapShot = await fire.database().ref('/users/' + userID + '/userName').once('value');
const userName = snapShot.val();
return {
userName: userName,
userID: userId
}
}
const userConvos = state.userProfile.convos;
let convoObj = {};
for (const key in userConvos) {
if (userConvos.hasOwnProperty(key)) {
const userId = userConvos[key];
const result = await fetchUserData(userId);
convoObj[key] = {
userName: result.userName,
userId: result.userId
}
}
}
commit('updateConvoObj', convoObj);
}
}
});
then call your actions before using getter in your sample.vue
:
await this.$store.dispatch('fetchAndUpdateConvoObj');
convoObj = this.$store.getters('getConvoObj');
wait for db and update store, then get its state.
doesnt make sense ?
Use vuexfire to connect your store directly to Realtime Database
another approach is this.
use vuexfire, then the state of the store is always up-to-date to realtime database, so you can call getters without calling actions.
i got tired to refactor / write a code, so google some sample if you wanna use that plugin :)
i refactored the original code a lot, so there should be some typo or mistake.
plz revise is if you find one.
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
-1
down vote
accepted
Why is this happening ?
Because you called async function synchronously.
lets make your code simpler.
getConvosObj: state => {
async function asyncFunction() {
// ...
}
asyncFunction();
}
at this point, your getConvosObj()
will return nothing, because getConvosObj()
ends before asyncFunction()
ends.
you need to wait until your asyncFunction()
ends, then your code should be like this:
getConvosObj: async state => { // <- changed here
async function asyncFunction() {
// ...
}
await asyncFunction(); // <- changed here too
}
but you should not do like this, because getters are not meant to be asynchronous by design.
this may work, but you should try a different approach.
So what should you do ?
Use actions before using getters
this is a basic approach.
async functions should be in actions.
so your store should be like this:
export default () =>
new Vuex.Store({
state: {
convoObj: null
},
mutations: {
updateConvoObj(state, payload) {
state.convoObj = payload;
}
},
actions: {
async fetchAndUpdateConvoObj({ state, commit }) {
const fetchUserData = async userId => {
const snapShot = await fire.database().ref('/users/' + userID + '/userName').once('value');
const userName = snapShot.val();
return {
userName: userName,
userID: userId
}
}
const userConvos = state.userProfile.convos;
let convoObj = {};
for (const key in userConvos) {
if (userConvos.hasOwnProperty(key)) {
const userId = userConvos[key];
const result = await fetchUserData(userId);
convoObj[key] = {
userName: result.userName,
userId: result.userId
}
}
}
commit('updateConvoObj', convoObj);
}
}
});
then call your actions before using getter in your sample.vue
:
await this.$store.dispatch('fetchAndUpdateConvoObj');
convoObj = this.$store.getters('getConvoObj');
wait for db and update store, then get its state.
doesnt make sense ?
Use vuexfire to connect your store directly to Realtime Database
another approach is this.
use vuexfire, then the state of the store is always up-to-date to realtime database, so you can call getters without calling actions.
i got tired to refactor / write a code, so google some sample if you wanna use that plugin :)
i refactored the original code a lot, so there should be some typo or mistake.
plz revise is if you find one.
add a comment |
up vote
-1
down vote
accepted
Why is this happening ?
Because you called async function synchronously.
lets make your code simpler.
getConvosObj: state => {
async function asyncFunction() {
// ...
}
asyncFunction();
}
at this point, your getConvosObj()
will return nothing, because getConvosObj()
ends before asyncFunction()
ends.
you need to wait until your asyncFunction()
ends, then your code should be like this:
getConvosObj: async state => { // <- changed here
async function asyncFunction() {
// ...
}
await asyncFunction(); // <- changed here too
}
but you should not do like this, because getters are not meant to be asynchronous by design.
this may work, but you should try a different approach.
So what should you do ?
Use actions before using getters
this is a basic approach.
async functions should be in actions.
so your store should be like this:
export default () =>
new Vuex.Store({
state: {
convoObj: null
},
mutations: {
updateConvoObj(state, payload) {
state.convoObj = payload;
}
},
actions: {
async fetchAndUpdateConvoObj({ state, commit }) {
const fetchUserData = async userId => {
const snapShot = await fire.database().ref('/users/' + userID + '/userName').once('value');
const userName = snapShot.val();
return {
userName: userName,
userID: userId
}
}
const userConvos = state.userProfile.convos;
let convoObj = {};
for (const key in userConvos) {
if (userConvos.hasOwnProperty(key)) {
const userId = userConvos[key];
const result = await fetchUserData(userId);
convoObj[key] = {
userName: result.userName,
userId: result.userId
}
}
}
commit('updateConvoObj', convoObj);
}
}
});
then call your actions before using getter in your sample.vue
:
await this.$store.dispatch('fetchAndUpdateConvoObj');
convoObj = this.$store.getters('getConvoObj');
wait for db and update store, then get its state.
doesnt make sense ?
Use vuexfire to connect your store directly to Realtime Database
another approach is this.
use vuexfire, then the state of the store is always up-to-date to realtime database, so you can call getters without calling actions.
i got tired to refactor / write a code, so google some sample if you wanna use that plugin :)
i refactored the original code a lot, so there should be some typo or mistake.
plz revise is if you find one.
add a comment |
up vote
-1
down vote
accepted
up vote
-1
down vote
accepted
Why is this happening ?
Because you called async function synchronously.
lets make your code simpler.
getConvosObj: state => {
async function asyncFunction() {
// ...
}
asyncFunction();
}
at this point, your getConvosObj()
will return nothing, because getConvosObj()
ends before asyncFunction()
ends.
you need to wait until your asyncFunction()
ends, then your code should be like this:
getConvosObj: async state => { // <- changed here
async function asyncFunction() {
// ...
}
await asyncFunction(); // <- changed here too
}
but you should not do like this, because getters are not meant to be asynchronous by design.
this may work, but you should try a different approach.
So what should you do ?
Use actions before using getters
this is a basic approach.
async functions should be in actions.
so your store should be like this:
export default () =>
new Vuex.Store({
state: {
convoObj: null
},
mutations: {
updateConvoObj(state, payload) {
state.convoObj = payload;
}
},
actions: {
async fetchAndUpdateConvoObj({ state, commit }) {
const fetchUserData = async userId => {
const snapShot = await fire.database().ref('/users/' + userID + '/userName').once('value');
const userName = snapShot.val();
return {
userName: userName,
userID: userId
}
}
const userConvos = state.userProfile.convos;
let convoObj = {};
for (const key in userConvos) {
if (userConvos.hasOwnProperty(key)) {
const userId = userConvos[key];
const result = await fetchUserData(userId);
convoObj[key] = {
userName: result.userName,
userId: result.userId
}
}
}
commit('updateConvoObj', convoObj);
}
}
});
then call your actions before using getter in your sample.vue
:
await this.$store.dispatch('fetchAndUpdateConvoObj');
convoObj = this.$store.getters('getConvoObj');
wait for db and update store, then get its state.
doesnt make sense ?
Use vuexfire to connect your store directly to Realtime Database
another approach is this.
use vuexfire, then the state of the store is always up-to-date to realtime database, so you can call getters without calling actions.
i got tired to refactor / write a code, so google some sample if you wanna use that plugin :)
i refactored the original code a lot, so there should be some typo or mistake.
plz revise is if you find one.
Why is this happening ?
Because you called async function synchronously.
lets make your code simpler.
getConvosObj: state => {
async function asyncFunction() {
// ...
}
asyncFunction();
}
at this point, your getConvosObj()
will return nothing, because getConvosObj()
ends before asyncFunction()
ends.
you need to wait until your asyncFunction()
ends, then your code should be like this:
getConvosObj: async state => { // <- changed here
async function asyncFunction() {
// ...
}
await asyncFunction(); // <- changed here too
}
but you should not do like this, because getters are not meant to be asynchronous by design.
this may work, but you should try a different approach.
So what should you do ?
Use actions before using getters
this is a basic approach.
async functions should be in actions.
so your store should be like this:
export default () =>
new Vuex.Store({
state: {
convoObj: null
},
mutations: {
updateConvoObj(state, payload) {
state.convoObj = payload;
}
},
actions: {
async fetchAndUpdateConvoObj({ state, commit }) {
const fetchUserData = async userId => {
const snapShot = await fire.database().ref('/users/' + userID + '/userName').once('value');
const userName = snapShot.val();
return {
userName: userName,
userID: userId
}
}
const userConvos = state.userProfile.convos;
let convoObj = {};
for (const key in userConvos) {
if (userConvos.hasOwnProperty(key)) {
const userId = userConvos[key];
const result = await fetchUserData(userId);
convoObj[key] = {
userName: result.userName,
userId: result.userId
}
}
}
commit('updateConvoObj', convoObj);
}
}
});
then call your actions before using getter in your sample.vue
:
await this.$store.dispatch('fetchAndUpdateConvoObj');
convoObj = this.$store.getters('getConvoObj');
wait for db and update store, then get its state.
doesnt make sense ?
Use vuexfire to connect your store directly to Realtime Database
another approach is this.
use vuexfire, then the state of the store is always up-to-date to realtime database, so you can call getters without calling actions.
i got tired to refactor / write a code, so google some sample if you wanna use that plugin :)
i refactored the original code a lot, so there should be some typo or mistake.
plz revise is if you find one.
answered Nov 9 at 9:22
sosmii
1047
1047
add a comment |
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53220270%2fasync-await-not-working-for-vuex-getter-but-works-for-log%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
2
How do you know your function return
undefined
?– ittus
Nov 9 at 5:42
I assume you think that
getConvosObj
will returnconvoObj
? Because it doesn't return anything.– robertklep
Nov 9 at 6:52
1
By design, getters are not meant to be asynchronous. As instead, they should return a certain store state and will be reactively updated when state changes. The fact, that code example above is quite hard to predict only proves that concept. Such approach also has performance flaws. Please, try to stick with original idea: calling actions -> changing state with mutations -> returning state with getters. This way flow is clear and debuggable.
– aBiscuit
Nov 9 at 6:54
Yes, I was trying to user the
getConvosObj
to returnconvoObj
. I'm fairly new to Vue so I didn't remember that I shouldn't do asynchronous stuff in getters. I've restructured it the way sosmii suggested below and it works now. Thanks everyone!– MrSpinn
Nov 9 at 16:35