MarioPhysics
MarioPhysics

Reputation: 11

How to use a promise with Firestore Firebase

I'm trying to read some data from Firestore using an array of keys and a map function, then, when all the data is back from Firestore, run a function on the resulting data set. This code works, but not in the right order; I'm struggling to make doSomethingUsefulWithData() delay until arrayOfDataFromFirestore is complete.

I've tried await but I get an error message saying "Uncaught syntax error: await is only valid in async functions and async generators". I think the awaits shown below are in the async function but apparently not.

If I run the version shown here, doSomethingUsefulWithData() runs before getData(), despite following it with a .then.

var arrayOfFirestoreKeys = [key0, key1, key3];
    
    function doSomethingUsefulWithData(){
        //Do something useful with the data here
    };
    
    function dataGet(){
        var arrayOfDataFromFirestore = [];
        arrayOfDataFromFirestore = Promise.all(arrayOfFirestoreKeys.map(async (dataGet, index) => {
            var docRef = db.collection('dataInFirestore').doc(arrayOfFirestoreKeys[index]).get().then((doc) => {
                if (doc.exists) {
                    console.log("Document data from async:", doc.data());
                    //doSomethingUsefulWithData here works but runs n times for n items in arrayOfFirestoreKeys
                };  
                //Trying await doSomethingUsefulWithData here produces warning 'await must be in async function or function generator'
            });
            //Trying await doSomethingUsefulWithData here produces warning 'await must be in async function or function generator'
        }))
        return(arrayOfDataFromFirestore);
    };
    
    arrayOfDataFromFirestore = dataGet().then(doSomethingUsefulWithData(arrayOfDataFromFirestore));
    //With this version of the code,
    //doSomethingUsefulWithData runs first and produces a complaint that arrayOfDataFromFirestore is undefined.
    //Then the contents of arrayOfDataFromFirestore follow into console.log

Upvotes: 0

Views: 190

Answers (1)

Renaud Tarnec
Renaud Tarnec

Reputation: 83093

If I correctly understand your question, the following should do the trick:

  var arrayOfFirestoreKeys = [key0, key1, key3];

  function doSomethingUsefulWithData(arrayOfSnapshots) {
    // arrayOfSnapshots is an Array of DocumentSnapshot
    arrayOfSnapshots.forEach(docSnap => {
        if (docSnap.exists) {
            // Do something
        }
    });
  }

  function dataGet() {
    const arrayOfDataFromFirestore = arrayOfFirestoreKeys.map((k) =>
      db.collection('dataInFirestore').doc(k).get()
    );
    return Promise.all(arrayOfDataFromFirestore);
  }

  dataGet().then(array => {
    doSomethingUsefulWithData(Array);
  });
  

Upvotes: 1

Related Questions