Reputation: 565
In my project I am getting order id's from firebase and then getting each order based on that id and finally want to push that order to my orderList array.
But orderList array is always empty, I think there is a problem when pushing values into array from inside a for loop but couldn't find a solution.
How can I fix this and push the values to orderList?
fetchOrders({commit, getters, state}) {
var orderList = [];
service.fetchUserOrdersIds(getters.user.id).then(snapshot => {
var tempOrderIds = snapshot.val();
for (let key in tempOrderIds) {
firebase
.database()
.ref("orders")
.child(tempOrderIds[key])
.once("value")
.then(orderSnap => {
orderList.push(orderSnap.val());
});
}
});
commit("setUserOrders", orderList);
}
EDIT: I have found a solution but its a bit dirty. There might be a better solution I think
fetchOrders({commit, getters, state}) {
var orderList = [];
service.fetchUserOrdersIds(getters.user.id).then(snapshot => {
var tempOrderIds = snapshot.val();
var size = Object.keys(tempOrderIds).length;
var i = 0;
for (let key in tempOrderIds) {
firebase
.database()
.ref("orders")
.child(tempOrderIds[key])
.once("value")
.then(orderSnap => {
orderList.push(orderSnap.val());
if (i == size) commit("setUserOrders", orderList);
});
i++;
}
});
},
Upvotes: 1
Views: 658
Reputation: 12808
Your commit()
function was receiving an empty orderList
because it was being fired before the promise
that filled the orderList
was fulfilled.
Here is a simple modification that keeps the code structure you setup - but waits to fire the commit()
function until the orderList
array is generated:
fetchOrders({commit, getters, state}) {
return service
.fetchUserOrdersIds(getters.user.id) // promist to get snapshot
.then(snapshot => { // promise to generate orders list based on snapshot
var listOfOrderPromises = [];
var tempOrderIds = snapshot.val();
for (let key in tempOrderIds) {
var thisOrderPromise = firebase // create a promise to get this order value
.database()
.ref("orders")
.child(tempOrderIds[key])
.once("value")
.then(orderSnap => {
return orderSnap.val();
});
listOfOrderPromises.push(thisOrderPromise); // append this promise to a list of promises (one for each order)
}
return Promise.all(listOfOrderPromises); // resolve all of the promises: generates your expected `orderList`
})
.then((orderList)=>{ // commit the orders from the resolved order List
commit("setUserOrders", orderList);
})
}
Note that the Promise.all()
function takes an array of promises (e.g., [promise_1, promise_2, ...]
) and resolves with an array of the values that resolve from each individual promise (e.g., [result_of_promise_1, result_of_promise_2, ...]
)
Upvotes: 1
Reputation: 155055
(Disclaimer: I'm not a Firebase user, but assuming it uses JavaScript Promises (Promise<T>
in TypeScript) the way I'm used to, then something like this should work.
Note the use of Promise.all
so that it waits for all of the firebase.database()...
calls/promises to complete before passing the resolved values into commit( "setUserOrders", ... )
.
service
.fetchUserOrdersIds( getters.user.id )
.then( snapshot => {
var tempOrderIds = snapshot.val();
var size = Object.keys( tempOrderIds ).length;
var i = 0;
var promises = tempOrderIds
.map( orderId => firebase
.database()
.ref( "orders" )
.child( orderId )
.once( "value" )
);
Promise
.all( promises )
.then( orderValues => {
orderValues = orderValues.map( e => e.val() );
commit( "setUserOrders", orderValues );
} );
}
Upvotes: 1