Reputation: 1679
I'm having issues trying to do some data processing while looping over some records from a firebase call. Within the loop, I'm making a firebase call to retrieve data, which I then want to use to update an element in the object array. I've provided a simplified version of the method below which exhibits the issue.
In this example, I want to insert new values into an array if they don't exist, then make a call to firebase to retrieve new data, the update the array elements.
Finally, I simply do a console.log to loop over the new array that should have been created to output new values. However, when the code runs, nothing is displayed, as if the array isn't created yet.
If I simply do console.log(newArray)
it shows the elements with the data.
But my issue is, I need to process those elements in the newArray
further...and it doesn't exist at that point in code.
I've tried wrapping the entire loop in a Promise.all[]
call, and using the .then()
method to loop over the newArray
elements, but that didn't work.
This seems like it should be easy, but I'm missing something that must be related to the async response from firebase.
TestArrayUpdates = () => {
namestoInsert = [
{ name: 'Bob', score: 5 },
{ name: 'Jim', score: 10 },
{ name: 'steve', score: 15 }
];
newArray = [];
let dayscore = 0;
namestoInsert.map((el, i) => {
let idx = newArray.findIndex(item => item.name == el.name);
if (idx == -1) {
firebase
.database()
.ref('userscoresbyday')
.child('2019-Aug-30')
.child('bgmd0r5HyZViLQZBynXUSm9e9Ab2')
.once('value', snap => {
if (snap.exists()) {
dayscore = snap.val().score;
}
})
.then(() => {
newscore = el.score + dayscore;
newArray.push({ name: el.name, score: newscore });
});
}
});
newArray.map((el, i) => {
console.log(el.name);
});
};
I expected the output to be list of names. Nothing is displayed.
Upvotes: 2
Views: 256
Reputation: 5082
As you correctly diagnosed yourself, you need to wait for all the stuff you're doing to be done, before you can output anything. The way to do that is by actually waiting for the promises you are creating. The following code should do that in theory. I can't fully test it as I have no access to that firebase
thing, but I am using a mockup.
FetchScore = (el) => new Promise( function(resolve, reject) {
console.log("Now asking database");
firebase
.database()
.ref('userscoresbyday')
.child( '2019-Aug-30' )
.child( 'bgmd0r5HyZViLQZBynXUSm9e9Ab2' ).
.once('value', snap => {
console.log("The database answered");
if( snap.exists() )
{
console.log("Found a score");
resolve( snap.val().score );
}
else
{
console.log("No points!");
resolve( 0 );
}
});
console.log("Done asking database");
});
TestArrayUpdates = ( namestoInsert ) => {
newArray = [];
console.log("Allright, here we go");
promises = namestoInsert.map( (el,i) => {
console.log("Here comes: " + el.name);
if( newArray.find(item => item.name == el.name) )
{
console.log("Skipping, I've seen them before");
return Promise.resolve(-1);
}
console.log(el.name + " is new in town!");
// then also returns a Promise
return FetchScore(el).then( (score) => {
if ( newArray.find( item => item.name == el.name ) )
{
console.log("Do nothing, we have already registered " + el.name);
}
else
{
console.log("Registering score for " + el.name);
newArray.push({'name': el.name, 'score': el.score + score })
}
});
});
console.log("All questions asked, waiting for " + promises.length + " answers.");
// Let's wait for all the promises to be kept
return Promise.all(promises).then( () => {
console.log("Here are our answers:");
// and then we output our stuff
newArray.map((el,i) => {
console.log(el.name + " = " + el.score);
})
console.log("We're done");
});
console.log("Everything is set up");
}
console.log("Am I really ...");
TestArrayUpdates( [{name: 'Bob', score: 5}, {name: 'Jim', score:10}, {name:'Steve', score:15}, {name:'Bob', score:15}] );
console.log("... already here????");
This produces the following output:
> Am I really ...
> Allright, here we go
> Here comes: Bob
> Bob is new in town!
> Now asking database about Bob
> Here comes: Jim
> Jim is new in town!
> Now asking database about Jim
> Here comes: Steve
> Steve is new in town!
> Now asking database about Steve
> Here comes: Bob
> Bob is new in town!
> Now asking database about Bob
> All questions asked, waiting for 4 answers.
> ... already here????
> The database answered
> Registering score for Bob
> The database answered
> Registering score for Jim
> The database answered
> Registering score for Steve
> The database answered
> Do nothing, we have already registered Bob
> Here are our answers:
> Bob = 16
> Jim = 21
> Steve = 26
> We're done
I hope this helps to wrap your head around what happens when.
Upvotes: 1