Tres
Tres

Reputation: 107

Firestore Offline Cache & Promises

This question is a follow-up on Firestore offline cache. I've read the offline cache documentation but am confused on one point.

One commenter answered in the prior question (~ year ago):

You Android code that interact with the database will be the same whether you're connected or not, since the SDK simply works the same."

In the API documentation for DocumentReference's set method, I just noticed that it says:

Returns non-null Promise containing void A promise that resolves once the data has been successfully written to the backend. (Note that it won't resolve while you're offline).

Emphasis mine. Wouldn't this bit in the documentation suggest that the code won't behave the same, or am I missing something? If I'm waiting on the .set() to resolve before allowing some user interaction, it sounds from this bit like I need to adjust the code for an offline case differently than I would normally.

The CollectionReference's add method worries me a bit more. It doesn't have exactly the same note but says (emphasis mine):

A Promise that resolves with a DocumentReference pointing to the newly created document after it has been written to the backend.

That is a little more vague as not sure if "backend" in this case is a superset of "cache" and "server" or if it's meant to denote only the server. If this one doesn't resolve, that would mean that the following wouldn't work, correct?

return new Promise((resolve, reject) => {
  let ref = firestore.collection(path)
  ref.add(data)
  .then(doc => {
    resolve({ id: doc.id, data: data })
  })
  ...
})

Meaning, the .add() would not resolve, .then() would not run, and I wouldn't have access to the id of the document that was just added. I hope I'm just misunderstanding something and that my code can continue to function as-is both online and offline.

Upvotes: 1

Views: 392

Answers (1)

Doug Stevenson
Doug Stevenson

Reputation: 317372

You have two of concerns here, which are not really related. I'll explain both of them separately.

For the most part, developers don't typically care if the promise from a document update actually resolves or not. It's almost always "fire and forget". What would an app gain to know that the update hit the server, as long as the app behaves the same way regardless? The local cache has been updated, and all future queries will show that the document has been updated, even if the update hasn't been synchronized with the server yet.

The primary exception to this is transactions. Transactions require that the server be online, because round trips need to be made between the client and server in order to ensure that the update was atomic. Transactions simply don't work offline. If you need to know if a transaction worked, you need to be online. Unlike normal document writes, transactions don't persist in local cache. If the app is killed before the transaction completes on the server, the transaction is lost.


Your second concern is about newly added documents where the id of the document isn't defined at the time of the update. It's true that add() returns a promise that only resolves when the new document exists on the server. You can't know the id of the document until the promise delivers you the DocumentReference of the new document.

If this behavior doesn't work for you, you can generate a new id for a document by simply calling doc() with no arguments instead of add(). doc() immediately returns the DocumentReference of the new (future) document that hasn't been written (until you choose to write it). In both the case of doc() and add(), these DocumentReference objects contain unique ids generated on the client. The difference is that with doc(), you can use the id immediately, because you get a DocumentReference immediately. With add(), you can't, because the DocumentReference isn't provided until the promise resolves. If you need that new document id right now, even while offline, use doc() instead of add(). You can then use the returned DocumentReference to create the document offline, stored in the local cache, and synchronized later. The update will then return a promise that resolves when the document is actually written.

Upvotes: 1

Related Questions