'Synchronously iterate through firestore collection

I have a firebase callable function that does some batch processing on documents in a collection.

The steps are

  1. Copy document to a separate collection, archive it
  2. Run http request to third party service based on data in document
  3. If 2 was successful, delete document

I'm having trouble with forcing the code to run synchronously. I can't figure out the correct await syntax.

async function archiveOrders  (myCollection: string) {

//get documents in array for iterating
const currentOrders = [];
console.log('getting current orders');
await db.collection(myCollection).get().then(querySnapshot => {
    querySnapshot.forEach(doc => {
        currentOrders.push(doc.data());
    });
});

console.log(currentOrders);

//copy Orders
currentOrders.forEach (async (doc) => {

    if (something about doc data is true ) {
        let id = "";
        id = doc.id.toString();
        await db.collection(myCollection).doc(id).set(doc);
        console.log('this was copied: ' + id, doc);
    }

});

}



Solution 1:[1]

To solve the problem I made a separate function call which returns a promise that I can await for. I also leveraged the QuerySnapshot which returns an array of all the documents in this QuerySnapshot. See here for usage.

// from inside cloud function
// using firebase node.js admin sdk

const current_orders = await db.collection("currentOrders").get();

for (let index = 0; index < current_orders.docs.length; index++) {
  const order = current_orders.docs[index];
  await archive(order);
}


async function archive(doc) {

    let docData = await doc.data();

if (conditional logic....) {
    try {
      // await make third party api request
      await db.collection("currentOrders").doc(id).delete();

    }
    catch (err) {
      console.log(err)
    }
} //end if

} //end archive

Solution 2:[2]

Now i'm not familiar with firebase so you will have to tell me if there is something wrong with how i access the data.

You can use await Promise.all() to wait for all promises to resolve before you continue the execution of the function, Promise.all() will fire all requests simultaneously and will not wait for one to finish before firing the next one.

Also although the syntax of async/await looks synchronous, things still happen asynchronously

async function archiveOrders(myCollection: string) {
  console.log('getting current orders')
  const querySnapshot = await db.collection(myCollection).get()
  const currentOrders = querySnapshot.docs.map(doc => doc.data())

  console.log(currentOrders)

  await Promise.all(currentOrders.map((doc) => {
    if (something something) {
      return db.collection(myCollection).doc(doc.id.toString()).set(doc)
    }
  }))

  console.log('copied orders')
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Mahesh Jamdade
Solution 2