I'm creating a project using Vue 3 as frontend.
In Dashboard.vue, a GET
request will be sent to backend with token in header, in order to let the backend identify user's identity, then Vue will receive the response with a json including info like this: {'uid': 'xxx', 'username': 'xxx'}
.
My Dashboard.vue:
<script>
import axios from 'axios';
export default {
data() {
return {
uid: '',
username: '',
temp: {},
loaded: false
}
},
methods: {
require_get(url) {
var token = localStorage.getItem('token');
var config = {
headers: {
'token': token,
}
};
var _url = 'user/dashboard/' + url;
axios.get(_url, config)
.then(response => {
this.temp = response.data;
})
},
get_user_info() {
this.require_get('info');
this.uid = this.temp['username'];
this.username = this.temp['username'];
}
},
mounted() {
this.get_user_info();
}
}
</script>
In this way, uid
and username
cannot be updated correctly.
For debugging, when I add console.log(this.uid)
at the end of get_user_info()
like this:
//...
this.require_get('info');
this.uid = this.temp['username'];
this.username = this.temp['username'];
console.log(this.temp['uid']);
I get a undefined
. But when I add console.log(this.uid)
at the end of require.get()
like this:
//...
.then(response => {
this.temp = response.data;
console.log(this.temp['uid]);
})
The output shows that variable uid
has already been updated at this moment.
After testing, I found that I can correctly update uid
and username
as long as I put
this.uid = this.temp['username'];
this.username = this.temp['username'];
inside require_get()
.
Why is that? And how can I manage to update these variables with these two codes staying in get_user_info()
?
I changed my codes into"
methods: {
async require_get(url) {
var token = localStorage.getItem('token');
var config = {
headers: {
'token': token,
}
};
var _url = 'user/dashboard/' + url;
axios.get(_url, config)
.then(response => {
return response.data;
})
},
async get_user_info() {
let info = await this.require_get('info');
console.log(info);
this.uid = info['username'];
this.username = info['username'];
}
},
mounted() {
this.get_user_info('info');
}
and the output of console.log(info)
is still undefined
, now I don't understand...
The issue is asynchronous execution.
In require_get
, you update this.temp
in the .then()
callback, which is only called when the Promise has resolved. In get_user_info
, you are calling require_get
and then immediately (synchronously) trying to read the data. Because it is fetched and set asynchronously, it is not yet present and you get undefined
.
To fix it, make require_get
an async function and return the data instead of using this.temp
. Then make get_user_info
an async function as well, await the call of require_get
, and assign this.uid
and this.username
to the returned data.
You could also use .then()
if you prefer that to async/await. I have included examples for both.
I assume that this.uid = data['username']
was meant to be this.uid = data['uid']
, so changed that too.
With async/await
import axios from 'axios';
export default {
data() {
return {
uid: '',
username: '',
loaded: false
}
},
methods: {
async require_get(url) {
var token = localStorage.getItem('token');
var config = {
headers: {
'token': token,
}
};
var _url = 'user/dashboard/' + url;
var response = await axios.get(_url, config);
return response.data;
},
async get_user_info() {
var data = await this.require_get('info');
this.uid = data['uid'];
this.username = data['username'];
}
},
mounted() {
this.get_user_info();
}
}
With .then()
import axios from 'axios';
export default {
data() {
return {
uid: '',
username: '',
loaded: false
}
},
methods: {
require_get(url) {
var token = localStorage.getItem('token');
var config = {
headers: {
'token': token,
}
};
var _url = 'user/dashboard/' + url;
return axios.get(_url, config).then((response) => response.data);
},
get_user_info() {
this.require_get('info').then((data) => {
this.uid = data['uid'];
this.username = data['username'];
});
}
},
mounted() {
this.get_user_info();
}
}