Home > Blockchain >  Firestore `addDoc()` function seems to resolve before the doc is created
Firestore `addDoc()` function seems to resolve before the doc is created

Time:12-11

I'm working with Firestore Web SDK v9 in an NodeJS environment. I do not use the live update but query data when needed.

My data is held in a local variable entries. After creating new entry in the Firestore collection entries, I try fetch all docs from this collection to update the local variable. But the newly added entry does not show up:

/// scaffolding:

import { initializeApp } from "firebase/app"
import { getFirestore, collection, addDoc, getDocs, query } from "firebase/firestore"

const app = initializeApp({
  apiKey: "...",
  authDomain: "...",
  projectId: "...",
  storageBucket: "...",
  messagingSenderId: "...",
  appId: "...",
})
const db = getFirestore(app)


/// payload:

let entries = []

try {

  // add doc to collection:

  const docRef = await addDoc(collection(db, "entries"), { foo: "bar" })
  console.log(docRef.id) // will print the id as expected
  
  // fetch all docs in collection:

  const q = query(collection(db, "entries")
  const querySnapshot = await getDocs(q)

  const result = []
  querySnapshot.forEach((doc) => {
    result.push({
      _id: doc.id,
      ...doc.data()
    })
  }
  entries = result // this will only contain the docs that have already existed BEFORE the addDocs() operation above

} catch (error) {
  console.log(error) // no error is being logged, so the above seems to work as expected
}

If I add a timeout of a couple of seconds between the add doc and fetch docs section, the local entries variable is populated as expected:

// add doc section

await new Promise((resolve) => {
  setTimeout(() => {
    resolve()
  }, 5000)
})

// fetch docs section

entries = result // will contain the newly created doc along with those that have already existed

I am confused by this behavior as the documentation for addDoc() states that the function will resolve after the newly created doc has been written to the backend:

Returns:

Promise<DocumentReference>

A Promise resolved with a DocumentReference pointing to the newly created document after it has been written to the backend (Note that it won't resolve while you're offline).

My app (it's running in the browser) is clearly online, and if it would be offline, the Promise should not resolve at all.

Does Firebase take additional time to process the new document? How can I wait for it to be available?

CodePudding user response:

Well I'm not sure why is that exactly happening but you can avoid this behavior by using onSnapshot feature on your collection like this:

import { onSnapshot } from "firebase/firestore";
const unsub = onSnapshot(collection(db, "groups"), (querySnapshot) => {
  console.log("Updated Docs: ", querySnapshot.docChanges);
  console.log("Docs: ", querySnapshot.docs);
});

By doing this, you can be informed whenever your docs on that collection being changed.

CodePudding user response:

A more elegant way to do this, which circumvents the issue completely, is to just push the object that was written to the doc to the local array:

let entries = []

const newEntry = { foo: "bar" }
await addDoc(collection(db, "entries"), newEntry)

entries.push(newEntry)

Another way that - surprisingly! - works is to not fetch the whole collection but only the newly created doc:

const entries = []

const docRef = await addDoc(collection(db, "entries"), { foo: "bar" });
const docSnapshot = await getDoc(docRef);
        
entries.push(docSnapshot.data());

I don't know why this works (while fetching the whole collection right after creating the doc will not return that doc as part of the result), but it works ...

  • Related