Reputation: 327
I am trying to fetch some data from firebase with 2 database calls. My strategy to get accounts only for 1 user is as follows:
My firebase structure look like this.
My problem is that the second fetch call always finishes last.
export const fetchAccounts = () => {
return (dispatch, getState) => {
const accounts = [];
const uid = getState().auth.uid;
return database.ref(`users/${uid}/accounts`).once('value').then((snapshot) => {
snapshot.forEach((element) => {
database.ref(`accounts/${element.key}`).once('value').then((snapshot) => {
accounts.push(snapshot.val());
console.log('snapshot: ', accounts);
})
});
console.log('Acc 1:', accounts);
}).then(() => {
console.log('Acc 2:', accounts)
})
// dispatch call with full array
}
};
I am calling action from main file
reduxStore.dispatch(fetchAccounts()).then(()=>{
renderApp();
});
Is it possible to wait for both database calls to finish and then call dispatch function with fully populated array? Appreciate any idea.
Upvotes: 0
Views: 1733
Reputation: 171679
Your first then()
doesn't return anything so the second then()
will fire immediately which is what you are seeing in the console. The loop of requests however are asynchronous and haven't completed yet
Create an array of promises and use Promise.all()
so the second then()
won't fire until the requests in the loop all complete.
export const fetchAccounts = () => {
return (dispatch, getState) => {
const accounts = [];
const uid = getState().auth.uid;
return database.ref(`users/${uid}/accounts`).once('value').then((snapshot) => {
const accountPromises =[];// array to store promises
snapshot.forEach((element) => {
// reference promise to pass into array
const request = database.ref(`accounts/${element.key}`).once('value').then((snapshot) => {
accounts.push(snapshot.val());
console.log('snapshot: ', accounts);
});
// push request promise to array
accountPromises.push(request)
});
console.log('Acc 1:', accounts);// accounts should still be empty here since requests are in progress
// return promise that doesn't resolve until all requests completed
return Promise.all(accountPromises);
}).then(() => {
// shouldn't fire until all the above requests have completed
console.log('Acc 2:', accounts);
return accounts // return array to use in next `then()`
})
// dispatch call with full array
}
};
Upvotes: 2