0

I have an area of my code where users of a group are stored in an array. In some cases, I want to gather additional data on the users.

Here is what I tried so far:

async getMembersData(groupUid) { const members = await this.getMembers(groupUid); var membersData = {}; Object.keys(members).map((key, i) => { const member = members[key]; firebase.database().ref(`users/${member.uid}`).once('value', snap => { membersData[member.uid] = { 'uid': member.uid, 'username': snap.child('username').val(), 'imageUrl': snap.child('imageUrl').val(), 'type': member.type, }; }); }); return membersData; } 

I have this code working similarly by setting state and using the firebase .on() function, but I need it to work with .once() and returning the object.

1
  • You may think it works with on(), but it'll actually be returning an empty object on the first call to getMembersData. You'll need to deal with the fact that the code is asynchronous, for example by using the approach in Renaud's answer. Commented Nov 28, 2019 at 23:51

1 Answer 1

2

The following should work. Since the once() method is asynchronous and returns a Promise with a DataSnapshot, we use Promise.all() to execute the different queries in parallel.

 async getMembersData(groupUid) { const members = await this.getMembers(groupUid); var membersData = {}; const promises = []; const memberTypes = []; Object.keys(members).map((key, i) => { const member = members[key]; promises.push(firebase.database().ref(`users/${member.uid}`).once('value')); memberTypes.push(member.type); }); const memberSnapshotsArray = await Promise.all(promises); memberSnapshotsArray.forEach((snap, index) => { //You may check here if the DataSnapshot exists (snap.exists()) const memberUid = snap.key; membersData[memberUid] = { 'uid': memberUid, 'username': snap.child('username').val(), 'imageUrl': snap.child('imageUrl').val(), 'type': memberTypes[index] }; //Note that returned values from Promise.all() will be in order of the Promises passed, regardless of completion order //This is why we can use memberTypes[index] }); return membersData; } 
Sign up to request clarification or add additional context in comments.

2 Comments

That won't compile because await can't be in a function body that isn't declared async (you're passing a new function to map as a callback). Even if you make it async, map is going to return immediately and not wait for the promise returned by the callback to resolve, so it will just return empty membersData.
@DougStevenson Thanks for having pointed out the problem Doug! Obviously I was too fast when writing the answer... I've adapted it by using Promise.all().

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.