blacKnight
blacKnight

Reputation: 173

How to save firebase returned data to a variable

I am coding for my React Native app and I am having trouble getting the data from the firebase return outside of the firebase.firestore().collection("test_data").doc(ID) loop. Whenever I check the dataArray variable after the loop it is empty. If I check it within the loop, the data is there. I think that it is a scope problem, but I just do not understand it. I also cannot call any user defined functions inside of the loop.

    try {
      let dataArray = [];
      // get the document using the user's uid
      firebase.firestore().collection("users").doc(uid).get()
      .then((userDoc) =>{
        // if the document exists loop through the results
        if (userDoc.exists) {
          data = userDoc.data().saved_data; // an array store in firebase

          data.forEach(ID => { // loop through array

            firebase.firestore().collection("test_data").doc(ID).get()
            .then((doc) => {
              dataArray.push(doc.data().test_data);
              console.log(dataArray) // the data shows
            })
              console.log(dataArray) // the data does not show
          })

        }
      })
    } 
    catch (error) {

    }
  }

Upvotes: 1

Views: 1019

Answers (1)

Flagship1442
Flagship1442

Reputation: 1726

You're looping through asynchronous calls, so your final console.log will trigger before the data has been received. Your first console.log only triggers after the data has been received.

So the code is working, but the function (promise) will resolve (as undefined, or void) before all the data has been received from your firebase calls.

If you want to return the array to the caller, you could do something like this:

function getDataFromServer() {
  // get the document using the user's uid
  return firebase.firestore().collection('users').doc(uid).get().then(userDoc => {
    // now we're returning this promise

    const dataArray = []; // can move this to lower scope
    // if the document exists loop through the results

    if (userDoc.exists) {
      const savedData = userDoc.data().saved_data; // an array store in firebase

      return Promise.all(
        // wait for all the data to come in using Promise.all and map
        savedData.map(ID => {
          // this will create an array
          return firebase.firestore().collection('test_data').doc(ID).get().then(doc => {
            // each index in the array is a promise
            dataArray.push(doc.data().test_data);
            console.log(dataArray); // the data shows
          });
        })
      ).then(() => {
        console.log(dataArray);
        return dataArray; // now data array gets returned to the caller
      });
    }

    return dataArray; // will always be the original empty array
  });
}

Now the function returns the promise of an array, so you could do...

const dataArray = await getDataFromServer()

or

getDataArrayFromServer().then(dataArray => {...})

Upvotes: 7

Related Questions