Gekkouga
Gekkouga

Reputation: 19

Javascript firebase functions are not executed in defined order

I have a website that utilises google firebase - firestore database. I have certain functions that get data from firestore and displays the data on the website on page load.

all_data = [];

//Get all documents in collection
function getAllDocuments() {
  console.log('getAllDocuments() executed');
  db.collection("All data").get().then((querySnapshot) => {
    console.log('Getting documents from firestore...');
    querySnapshot.forEach((doc) => {
      //Creating object
      data_t = new dbData;
      all_data.push(data_t);
    });
  });
  console.log('All data:', all_data.length);
}

//Display documents
function displayDocuments(data) {
  console.log('displayDocuments() executed');
  //Other lines of code
}

//Functions to run on page load
function pageLoad() {
  getAllDocuments();
  displayDocuments(all_data);
}
window.onload = pageLoad;

However, the functions are executed before data is retrieved from firebase. So, my website loads as an empty page. I have to execute the displayDocuments() again to display the data on the screen.
I understand the problem behind this. The webpage is not getting my documents from firebase on page load. Even though pageLoad() executes getAllDocuments(), it skips the db.collection.get() initially. This method is executed only after window.onload is executed, that is, after all my pageLoad() are executed. My console output looks like

getAllDocuments() executed
All data: 0
displayDocuments() executed
Getting documents from firestore...

Does anyone know why db.collection.get() is not executed in the defined order? How db.collection().get() gets executed at the end without getAllDocuments() being called?

Upvotes: 0

Views: 41

Answers (2)

Pawan Sharma
Pawan Sharma

Reputation: 2342

The reason why this is happening is because your getAllDocuments function finishes its execution before the promise could resolve.

What you can do is make getAllDocuments async and wait for promise to resolve using await, and call it from pageLoad() function using await. i.e

all_data = [];

async function getAllDocuments() {
    console.log('getAllDocuments() executed');
    const querySnapshot = await db.collection("All data").get();
    querySnapshot.forEach((doc) => {
      //Creating object
      data_t = new dbData;
      all_data.push(data_t);
    });
    console.log('All data:', all_data.length);
}

async function pageLoad() {
  await getAllDocuments();
  // displayDocuments(all_data);
}

Upvotes: 1

Virtuoz
Virtuoz

Reputation: 914

You need to await the result of the first function since it performs an asynchronous action. You can do it by returning the promise directly. In this case, you don't need all_data global variable since you can return it from promise.

Something like that should work for you:

//Get all documents in collection
function getAllDocuments() {
  console.log('getAllDocuments() executed');
  return db.collection("All data").get().then((querySnapshot) => {
    console.log('Getting documents from firestore...');
    return querySnapshot.map((doc) => {
      //Creating object using doc
      // ....
      return new dbData;

    });
  });
}

//Display documents
function displayDocuments(data) {
  console.log('displayDocuments() executed');
  //Other lines of code
}

//Functions to run on page load
function pageLoad() {
  getAllDocuments().then(all_data => displayDocuments(all_data));
}
window.onload = pageLoad;

Upvotes: 1

Related Questions