themenace
themenace

Reputation: 2800

Firebase Firestore: when do promises from offline write operations resolve?

I activated offline as stated in the docs like:

firebase
    .firestore()
    .enablePersistence()
    .then(() => {
      console.log('offlinemode acctivated')
    })

The log appears as I would expect.

When adding data like so:

db
    .collection('foo')
    .add({foo: 'bar'})
    .then(docRef => {
      console.log('Added Foo: ', docRef.id)
      // do some stuff here with the newly created foo and it's id.
    })
    .catch(console.error)

Neither .then() nor .catch() are getting called while offline. This is even though the object is added to the foo collection in my offline DB as this callback is executed:

db
    .collection('foo')
    .onSnapshot(callback)

Am I missing something? I would expect the promise to either fail or resolve, so I can react accordingly.

Upvotes: 7

Views: 1292

Answers (2)

Joao
Joao

Reputation: 2746

Here's my solution:

  1. I wrap the call in a function that should eventually return a resolving promise no matter the offline/online status
  2. I then get the saved doc from onSnapshot which returns the doc written to local cache (works both online and offline).

Here's my code (with a little typescript):

export function dbWritePromise(functionPromise: Promise<any>): Promise<any>{
  if(window.navigator.onLine){
    return functionPromise
  }
  else{
    return Promise.resolve()
  }
}

// I grabbed this function from a Github issue one upon a time
export function docSnapshotPromise(ref: firebase.firestore.DocumentReference): Promise<any>{
  return new Promise((resolve, reject) => {
    const unsubscribe = ref.onSnapshot(doc => {
      resolve(doc)
      unsubscribe()
    }, err => {
      reject(err)
      unsubscribe()
    })
  })
}

In use (I'm using the update function here, but add would work the same way) This code is working with documents from a collection called organizations:

try{
  //update org doc
  await dbWritePromise(orgRef.update({
    name: 'New and improved name here'
  }))
  // wait for this updated doc to be written to local cache, then we can get the updated org
  const updatedOrgRef = await docSnapshotPromise(orgRef)
  const updatedOrg = updatedOrgRef.data()
  console.log(updatedOrg.name) // outputs the new and improved name
}
catch (err) { handleError(err) }

The error thrown might be some error with local cache, or it might be a server error such as a permissions error returned by the Firestore rules (when online). Obviously any error from the server during offline mode would silently fail, even when the app is back online.

I'd love to see other peoples' solutions here!

Upvotes: 0

Doug Stevenson
Doug Stevenson

Reputation: 317372

Promises from write operations in Firestore will only resolve when there is confirmation from the server that the write completed, even though they may successfully be written to local cache.

Upvotes: 5

Related Questions