Reputation: 85
I have the following code that works when I uncomment the "return" in fetchData
below. How can I set it up so I wait for this.fetchData
to finish to fill items? I have tried variants of other promises, async, await, but cannot get it to actually work...
So far I set a this.items
inside fetchData
but I realize it's absolutely not what I want to actually do. It shows me the first X lines of my call, because of setting it this way, but all the code that is supposed to happen after the fetchData
call is bugging, starting with trying to do items.length
.
import axios from 'axios';
new Vue({
el: '#app',
data() {
return {
search: '',
totalItems: 0,
items: [],
loading: true,
pagination: {},
headers: [ //some headers
],
items: []
}
},
watch: {
pagination: {
handler () {
this.getDataFromApi()
.then(data => {
this.items = data.items
this.totalItems = data.total
})
},
deep: true
}
},
mounted () {
this.getDataFromApi()
.then(data => {
this.items = data.items
this.totalItems = data.total
})
},
methods: {
fetchData() {
axios.get('/api/v1/translations').then(response => {
//console.log(response.data)
this.items = response.data.data
})
//the return below is working 100%:
//return [{id:1,key:1,lg:'en',text:'woopie'}];
},
getDataFromApi () {
this.loading = true
return new Promise((resolve, reject) => {
const { sortBy, descending, page, rowsPerPage } = this.pagination
let items = this.fetchData()
const total = items.length
//some code to setup pagination and sort
setTimeout(() => {
this.loading = false
resolve({
items,
total
})
}, 1000)
})
}
},
})
Upvotes: 5
Views: 23956
Reputation: 1073978
Updated answer:
Apologies, in my original answer below I completely missed this:
So far I set a
this.items
insidefetchData
but I realize it's absolutely not what I want to actually do.
My answer assumed you did want this.items
. Sorry about that.
To just get the info from fetchData
without using this.items
, use the then
handler on the promise from axios.get
to return a new promise (remember, then
and catch
return promises) that resolves with response.data.data
:
fetchData() {
// vvvvvv------------------------
return axios.get('/api/v1/translations').then(response => {
return response.data.data;
// ^^^^^^^^^^^^^^^^^^^^^^^^^
})
},
This can be written more succinctly:
fetchData() {
return axios.get('/api/v1/translations').then(response => response.data.data);
},
Then, in getDataFromApi
, use a then
handler on that promise:
getDataFromApi () {
this.loading = true
return this.fetchData().then(items => {
// You might use this at some stage: const { sortBy, descending, page, rowsPerPage } = this.pagination
this.loading = false;
return { items, total: items.length };
});
}
Note that it's important that the consumer of getDataFromApi
handles promise rejection (e.g., uses a catch
handler on it). If you don't want the consumer to do that, don't return the promise, and use a catch
within getDataFromApi
instead.
Original answer:
You return the promise from axios.get
:
fetchData() {
// vvvvvv------------------------
return axios.get('/api/v1/translations').then(response => {
//console.log(response.data)
this.items = response.data.data
})
},
...and then use it rather than creating a new one in getFromApi
:
getDataFromApi () {
this.loading = true
return this.fetchData().then(() => {
// You might use this at some stage: const { sortBy, descending, page, rowsPerPage } = this.pagination
this.loading = false;
return { items: this.items, total: this.items.length };
});
}
Remember that then
(and catch
) create new promises; there's no reason for new Promise
if you already have a promise to work with. More on that part: What is the explicit promise construction antipattern and how do I avoid it?
(Note that I'm assuming you want this.items
on the instance for some reason. If you didn't, you'd just want to use response.data
as the return value of your axios.get...then
callback and use it in getDataFromApi
.)
Upvotes: 6