prozac
prozac

Reputation: 375

Firebase Database Snapshot ForEach Async Await

async/await doesn't seem to work with firebase forEach. This code runs console.log for the first child of the snapshot and then just hangs. Is this a bug or am I missing something?

main()
async function main() {
  const snap = await root.ref('somepath')
    .once('value')

  snap.forEach(async val => {
    await console.log(val.key)

  })
}

Upvotes: 13

Views: 10407

Answers (2)

Artur Owczarek
Artur Owczarek

Reputation: 1167

I use something like this:

import * as admin from "firebase-admin";

type FunctionOnDataSnapshot = (childSnapshot: admin.database.DataSnapshot) => Promise<any>;
export const asyncForEach = async (dataSnapshot: admin.database.DataSnapshot, childFunction: FunctionOnDataSnapshot) => {
    const toWait = [];
    dataSnapshot.forEach(childSnapshot => {
        toWait.push(childFunction((childSnapshot)));
    });
    await Promise.all(toWait);
};

Upvotes: 5

Karamell
Karamell

Reputation: 1032

It's an unintentional consequence of a feature, sometimes knows as a bug. From the firebase documentation: Firebase documentation

an async function always returns a Promise. And a promise is true-y value:

!!Promise.resolve===true.

As a workaround, try this solution:

main()
async function main() {
  const snap = await root.ref('somepath')
    .once('value')

  snap.forEach(function wrapper(){async val => {
    await console.log(val.key)
  }})

It won't wait for the promise to complete before moving to the next snapshot though. That would require a bit more code, but that may not be what you need anyways.

Upvotes: 11

Related Questions