5

I have been using parse-server as my backend and now migrating all my stuff to FireStore (specifically for storing additional user data). Now, with parse I could directly get the user data just by using ParseUser.getCurrentUser().getString(...). If I use FireStore, I have created a users collection and I can store a document for each user and it also supports local storage with offline support. But the problem I am facing is that I always need to use asynchronous/callback methods to get data from a document. Here is an example in android:

final DocumentReference docRef = mFirestore
                    .collection(USER_COLLECTION).document(mAuthApi.getCurrentUserId());
            docRef.get(Source.CACHE).addOnCompleteListener(task -> {
                if(task.isSuccessful()) {
                    ......
                } else {
                    ......
                }
            });

Is there a way where we can directly get data synchronously from DocumentReference assuming it is locally cached? Something like:

mFirestore.collection(USER_COLLECTION).document(mAuthApi.getCurrentUserId()).getString(...)

That would make things very easy for me as I need to replace ParseUser.getCurrentUser().getString(...) with an equivalent FireStore call in my entire code base.

Swapnil
  • 1,870
  • 2
  • 23
  • 48
  • 1
    I think the basic answer here is: no. – André Kool Jun 06 '18 at 12:28
  • If I understand you correctly in Firestore you can configure offline persistence, if you have enabled offline persistence, your listeners will receive listen events when the locally cached data changes –  Jun 06 '18 at 12:31

2 Answers2

1

Is there a way where we can directly get data synchronously from DocumentReference assuming it is locally cached?

No, there is not in terms of responsive applications. You cannot force the retrieval of the data from the cache while you're connected to the server, as you cannot stop the retrieval of the data from the cache while you are not connected to the server.

But not only Firebase Realtime Database or Cloud Firestore loads data asynchronously, almost all of modern other web APIs do, since it may take some time to get the data. So if you will force to get the data synchronously it will lead to unresponsive application dialogs for your users.

The initial response for most developers is to try and "fix" this asynchronous behavior, which I personally recommend against this. The web is asynchronous, and as soon as you accept that, you'll learn how to become productive with modern web APIs.

There is a very interesting post that was writen by Doug Stevenson, which will help you better understand this concept.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • 12
    Sometimes, you really do need synchronous queries, especially when you are *already* handling data in the background. The pattern you describe here is great when you are interacting with UI elements, but terrible when you need to load in sequence. – Brill Pappin Mar 12 '19 at 04:46
  • @BrillPappin Even if you need to to load data in sequence, you still need to get it asynchronous and this is because, getting data takes time. – Alex Mamo Mar 12 '19 at 08:37
  • 2
    No, you dont always have to do that. Take a background sync process for instance, it's already in it's own thread, and it can take as long as it needs without interrupting the user experiance (essentially doing the same thing as an async process already). What's vital about that situation, is that everything happens in order. For instance, you might need to know all your creates happen before your updates or deletes. If each call is asynchronous, you end up in a race condition. – Brill Pappin Mar 12 '19 at 14:47
  • 3
    @BrillPappin https://stackoverflow.com/a/47021042/3994127 here's the answer you were looking for, use DocumentSnapshot doc = Tasks.await(task); – Raghav Satyadev Nov 11 '19 at 09:28
0

It looks like you can use a Future based API, like the following line to execute lines in order as if they were synchronous events.

final documents = await Firestore.instance.document("/user/$_userId").collection('reviews').getDocuments();
Elletlar
  • 3,136
  • 7
  • 32
  • 38
eimmer
  • 1,537
  • 1
  • 10
  • 29