I have a Vue application. I would like to retrieve entries (from a database) based on a userid. I have the following methods in Vue:
export default {
name: 'Entries',
data() {
return {
userid: null
};
},
methods: {
getEntries() {
this.getUserID();
console.log("userid getEntries: " + this.userid);
axios.get('/entries', this.userid)
.then((res) => {
this.entries = res.data;
console.log(this.entries);
})
.catch((error) => {
console.error(error);
});
},
getUserID() {
axios.get('/userid')
.then((res) => {
this.userid = res.data;
console.log("userid getUserId: " + this.userid );
})
.catch((error) => {
console.error(error);
});
},
},
created() {
this.getEntries();
}
};
Within the getEntries method, I'm immediately calling the getUserID function. I would assume this sets the variable userid to the value retrieved from the getUserID method.
Instead I get the following output in the browser console, in exactly this order:
userid getEntries: null
userid getUserId: user_a
Why does it print first the console output from the getEntries function? And why is this null if it first executes the getUserID method?
How could I change is so that the axios call /entries can pass the userid.
axios calls are async, if you need the userid populated before anything else is called, then you should populate before anything else is called, in mounted/created.
Then you can react to its change with a watcher. You could call getEntries when the getUserID call resolves but it's dirty and couples the two methods.
And don't forget to assign entries in data.
This will work:
export default {
name: 'Entries',
data() {
return {
userid: null,
entries: []
};
},
watch: {
userid (v) {
if (v) this.getEntries()
}
},
mounted() {
this.$nextTick(this.getUserID)
},
methods: {
getEntries() {
console.log("userid getEntries: " + this.userid);
axios.get('/entries', this.userid)
.then((res) => {
this.entries = res.data;
console.log(this.entries);
})
.catch((error) => {
console.error(error);
});
},
getUserID() {
axios.get('/userid')
.then((res) => {
this.userid = res.data;
console.log("userid getUserId: " + this.userid);
})
.catch((error) => {
console.error(error);
});
}
}
};
Using async/await
export default {
name: 'Entries',
data() {
return {
userid: null,
entries: []
};
},
watch: {
userid (v) {
if (v) this.getEntries()
}
},
mounted() {
this.$nextTick(this.getUserID)
},
methods: {
async getEntries() {
try {
const { data } = await axios.get('/entries', this.userid)
this.entries = data;
} catch (error) {
console.error(error);
}
},
async getUserID() {
try {
const { data } = await axios.get('/userid')
this.userid = data;
} catch (error) {
console.error(error);
}
}
}
};
Since getUserId is asynchronous, it doesn't return immediately. You therefore need to wait for it to return before continuing. This can be done using then but, nested Promises are a bit unpleasant to work with. A simpler option is to use async/await instead:
async getEntries() {
await this.getUserID();
console.log("userid getEntries: " + this.userid);
axios.get('/entries', this.userid)
.then((res) => {
this.entries = res.data;
console.log(this.entries);
})
.catch((error) => {
console.error(error);
});
},